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

Jac*_*ack 3 c malloc memory-management

我对 malloc() 函数有点困惑。

如果sizeof(char)1 byte并且malloc()函数接受参数中的 N 个字节进行分配,那么如果我这样做:

char* buffer = malloc(3);
Run Code Online (Sandbox Code Playgroud)

我分配了一个可以存储3个字符的缓冲区,对吧?

char* s = malloc(3);
int i = 0;
while(i < 1024) { s[i] = 'b'; i++; }
s[i++] = '$';
s[i] = '\0';
printf("%s\n",s);
Run Code Online (Sandbox Code Playgroud)

效果很好。并将 1024 存储b'ss.

bbbb[...]$
Run Code Online (Sandbox Code Playgroud)

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

Tim*_*nes 5

malloc(size)size返回内存中至少有字节可供您使用的位置。您可能能够立即写入 后的字节s[size],但是:

  • 这些字节可能属于程序的其他位,这将在稍后的执行中引起问题。
  • 或者,这些字节可能适合您写入 - 它们可能属于您的程序使用的页面,但不用于任何用途。
  • malloc()或者,它们可能属于用于跟踪程序所使用内容的结构。破坏这个是非常糟糕的!
  • 或者,它们可能不属于您的程序,这将导致立即出现分段错误。如果您访问说,这很可能s[size + large_number]

很难说哪一种会发生,因为访问您请求的空间之外malloc()将导致未定义的行为。

在您的示例中,您溢出了 buffer,但不会导致立即崩溃。请记住,C 对数组/指针访问不进行边界检查。


另外,malloc()在堆上创建内存,但缓冲区溢出通常与堆栈上的内存有关。如果您想创建一个作为练习,请使用

char s[3];
Run Code Online (Sandbox Code Playgroud)

反而。这将在堆栈上创建一个包含 3 个字符的数组。在大多数系统上,数组后面不会有任何可用空间,因此后面的空间s[2]将属于堆栈。写入该空间可能会覆盖堆栈上的其他变量,并最终通过(例如)覆盖当前堆栈帧的返回指针而导致分段错误。


另一件事:

如果sizeof(char)是1字节

sizeof(char)实际上标准定义为始终为 1 字节。然而,在外来系统上,1 个字节的大小可能不是 8 位。当然,大多数时候你不必担心这个。