尝试缓冲malloc()分配的溢出值

时间:2012-03-28 04:54:56

标签: c memory-management malloc

我对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[...]$

为什么上面的代码不会导致缓冲区溢出?谁能解释一下?

6 个答案:

答案 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)

您是否尝试在发布模式下执行代码,或者您是否尝试释放自己的内存?这是一种未定义的行为。

这是一种语言黑客攻击,并且对它的使用有点怀疑。