我对malloc()函数有点困惑。
如果sizeof(char)
1 byte
并且malloc()
函数接受要分配的参数中的N个字节,那么如果我这样做:
char* buffer = malloc(3);
我分配一个可以存储3个字符的缓冲区,对吗?
char* s = malloc(3);
int i = 0;
while(i < 1024) { s[i] = 'b'; i++; }
s[i++] = '$';
s[i] = '\0';
printf("%s\n",s);
它工作正常。并在b's
中存储1024 s
。
bbbb[...]$
为什么上面的代码不会导致缓冲区溢出?谁能解释一下?
答案 0 :(得分:3)
malloc(size)
返回内存中至少size
字节可供您使用的位置。您可能能够在s[size]
之后立即写入字节,但是:
malloc()
用于跟踪您的程序使用的结构。腐败这是非常糟糕的!s[size + large_number]
很难说哪一个会发生,因为在您询问malloc()
的空间外访问会导致未定义的行为。
在您的示例中,您正在溢出缓冲区,但不会导致立即崩溃。请记住,C不对数组/指针访问进行边界检查。
此外,malloc()
在堆上创建内存,但缓冲区溢出通常与堆栈上的内存有关。如果您想创建一个作为练习,请使用
char s[3];
代替。这将在堆栈上创建一个包含3个字符的数组。在大多数系统上,阵列后面没有任何空闲空间,因此s[2]
之后的空间将属于堆栈。写入该空间可能会覆盖堆栈上的其他变量,并最终通过(例如)覆盖当前堆栈帧的返回指针来导致分段错误。
另一件事:
如果
sizeof(char)
是1个字节
sizeof(char)
实际上由标准定义为始终为1个字节。但是,在异域系统上,该1字节的大小可能不是8位。当然,大多数时候你不必担心这个。
答案 1 :(得分:1)
未定义行为(UB)写入超出已分配内存的范围。
任何行为都是可能的,UB&amp; amp;可以遇到任何行为 UB不一定保证分段错误。
答案 2 :(得分:1)
在某种程度上,你确实溢出了3个字符的缓冲区。但是,您还没有溢出程序的地址空间(尚未)。所以你完全超出了s *的范围,但是你在你的程序中覆盖随机的其他数据。因为你的程序拥有这些数据,所以程序不会崩溃,但仍然会做非常非常错误的事情,并且未来的行为是未定义的。
答案 3 :(得分:1)
实际上,这样做会破坏堆。效果可能不会立即出现(实际上,这是使PITA调试此类错误的部分原因)。但是,您可能会丢弃碰巧在堆中的任何其他内容,或者在程序的地址空间的那部分中。您可能还删除了malloc()
内部数据结构,因此后续的malloc()
或free()
调用可能会导致您的程序崩溃,导致许多程序员(错误地)相信他们已经在malloc()
中发现了一个错误。
答案 4 :(得分:0)
你正在溢出缓冲区。这取决于你要溢出的内存来获取错误信息。
答案 5 :(得分:0)
您是否尝试在发布模式下执行代码,或者您是否尝试释放自己的内存?这是一种未定义的行为。
这是一种语言黑客攻击,并且对它的使用有点怀疑。