这是我的代码。
int main()
{
char *s;
int i = 0;
printf("%lu n", sizeof(s));
s = malloc(sizeof(char) * 2);
printf("%lu n", sizeof(s));
/*Why is this working?*/
while (i <= 5)
{
s[i] = 'l';
i++;
}
printf("%s n", s);
printf("%lu n", sizeof(char));
printf("%lu n", sizeof(s[0]));
}
我认为,这应该是我试图比分配更多的写作时要记住的。为什么工作?
我认为,这应该是我试图比分配更多的写作时要记住的。为什么这可以工作?
这不是"工作";您的代码调用不确定的行为。"未定义的行为"并不意味着"您的代码将segfault segfault"。那将是定义的行为。UB意味着任何事情都可能发生。
在这种情况下,您正在踩在不拥有的内存上。这有时会遇到segfault,但不要指望它。C没有" segfaults"的概念,来自您的操作系统。
segfault是从操作系统的 signal 告诉您,访问特定的存储区与您的业务无关。碰巧的是,您要访问的内容不会触发OS的内存管理单元中的警报。有很多方法可以利用(覆盖函数调用,通过覆盖堆栈值对二进制的攻击等)。
)。也可能是您的Malloc不仅分配这两个字节和2个字节。Malloc调用一个系统调用,该系统调用虚拟内存页面(可能大于2个字节)。该SYSCALL(分别用于Linux和Windows的sbrk
和VirtualAlloc
)告诉OS将这些页面映射到您需要的内容上,然后保护它们,以使其没有其他任何人(读:读:另一个过程/应用程序)在您的存储区域上意外踩踏那个情况下,操作系统会用segfault击中一个人的头)。
还有其他提到的不确定的行为。
在插图中与附加变量的少量添加的代码以完全相同的方式声明,并在char *s
之后立即使用malloc'ed。
尽管不保证
将变量顺序存储在内存中,以这种方式创建它们使其很高的可能性。如果是这样,char *t
现在将拥有char *s
将侵占的空间,而您 Will 获得SEG故障:
int main()
{
char *s;
char *t;//addition
int i = 0;
printf("%lu n", sizeof(s));
s = malloc(sizeof(char) * 2);
t = malloc(sizeof(char) * 2);//addition
printf("%lu n", sizeof(s));
/*Why is this working?*/
while (i <= 5)
{
s[i] = 'l';
i++;
}
printf("%s n", s);
printf("%lu n", sizeof(char));
printf("%lu n", sizeof(s[0]));
}
注意: 在我使用的环境中(Windows 7,Ni运行时,调试等),我以任何一种支持其他答案中的未定义行为断言。
似乎是这样的:malloc分配了一些字节,多于您指定的。
使用malloc(sizeof(s)*2);//8然后(i&lt; = 36)还可以,但是(i&lt; = 37)已经不是..
使用例如malloc(sizeof(s)*4);//16然后(i&lt; = 7572)还可以,但是(i&lt; = 7573)已经不是..
(我在Code :: Blocks中进行了测试)
太糟糕了,丹尼斯·里奇(Dennis Ritchie)死了,这仍然是一个大谜那,但是只是不必太担心它总是足够分配您需要,无效终止字符串
正如其他人所说的那样,它的命中率或错过了代码是在生产中导致运行时错误,因为界限检查未内置在C 中(与语言不同,Java或C#)。该代码将在内存检查器下引起错误。
您可能知道Valgrind,所以这是读者的练习。这是Clang的地址消毒剂(我添加了一个printf("malloc: %p n", s);
)的情况:
$ ./t.exe | /usr/local/bin/asan_symbolize.py
malloc: 0x60200000b3b0
=================================================================
==98557==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000b3b2 at pc 0x1065c4b5b bp 0x7fff5963b810 sp 0x7fff5963b808
WRITE of size 1 at 0x60200000b3b2 thread T0
#0 0x1065c4b5a (/Users/jwalton/./t.exe+0x100000b5a)
#1 0x7fff870e27e0 (/usr/lib/system/libdyld.dylib+0x27e0)
#2 0x0
0x60200000b3b2 is located 0 bytes to the right of 2-byte region [0x60200000b3b0,0x60200000b3b2)
allocated by thread T0 here:
#0 0x1065d8cd5 (/usr/local/lib/clang/3.3/lib/darwin//libclang_rt.asan_osx_dynamic.dylib+0xfcd5)
#1 0x1065c4971 (/Users/jwalton/./t.exe+0x100000971)
#2 0x7fff870e27e0 (/usr/lib/system/libdyld.dylib+0x27e0)
#3 0x0
Shadow bytes around the buggy address:
0x1c0400001620: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400001630: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400001640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400001650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x1c0400001660: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x1c0400001670: fa fa fa fa fa fa[02]fa fa fa 00 00 fa fa fd fa
0x1c0400001680: fa fa fd fa fa fa 00 00 fa fa fd fa fa fa fd fa
0x1c0400001690: fa fa 00 00 fa fa 00 00 fa fa fd fa fa fa fd fa
0x1c04000016a0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x1c04000016b0: fa fa 00 00 fa fa fd fa fa fa fd fa fa fa 00 00
0x1c04000016c0: fa fa 00 00 fa fa fd fa fa fa fd fa fa fa 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==98557==ABORTING