写出比malloced更多的字符。 为什么不失败?

为什么以下工作并没有抛出某种分段错误?

char *path = "/usr/bin/"; char *random = "012"; // path + random + \0 // so its malloc(13), but I get 16 bytes due to memory alignment (im on 32bit) newPath = (char *) malloc(strlen(path) + strlen(random) + 1); strcat(newPath, path); strcat(newPath, "random"); // newPath is now: "/usr/bin/012\0" which makes 13 characters. 

但是,如果我添加

 strcat(newPath, "RANDOMBUNNIES"); 

不应该这个调用失败,因为strcat使用的内存多于分配的内存? 因此,不应该

 free(newPath) 

也失败因为它试图释放16个字节,但我使用了26个字节(“/ usr / bin / 012RANDOMBUNNIES \ 0”)?

非常感谢你提前!

大多数情况下,这种超限问题并不会使你的程序在烟雾和硫磺燃烧的气味中爆炸。 它更加微妙:在溢出变量之后分配的变量将被更改,从而导致程序无法解释且看似随机的行为。

整个程序片段是错误的。 您假设malloc()返回至少将第一个字节设置为0 。 通常情况并非如此,所以即使你的“安全” strcat()也是错误的。

但是,正如其他人所说的那样,未定义的行为并不意味着你的程序会崩溃。 这只意味着它可以做任何事情 (包括崩溃,但如果你不幸的话也不会崩溃)。

(另外,你不应该转换malloc()的返回值。)

写入比malloced更多的字符是未定义的行为
未定义的行为意味着任何事情都可能发生,行为无法解释。

由于访问无效的存储器部分,通常会发生分段故障。 这里它不会给出错误(分段错误)因为你仍然可以访问内存。 但是,您要覆盖未定义行为的其他内存位置,您的代码运行正常。

它将失败并且不会随机失败,具体取决于malloc内存之后的内存可用性。

此外,当你想随机连续时,你不应该引用引号。 那应该是

 strcat(newPath, random); 

许多C库函数不检查它们是否溢出。 它由程序员来管理分配的内存。 您可能只是在内存中写入另一个变量,对程序的操作具有不可预测的影响。 C的设计旨在提高效率,而不是指出编程中的错误。

你有这个电话好运。 你没有得到段错误,因为你的电话大概停留在地址空间的分配部分。 这是未定义的行为。 已写入的最后一个字符不保证不会被覆盖。 此调用也可能失败。

缓冲区溢出不保证会导致段错误。 行为很简单。 你可能会忘记写入一次不属于你的内存,再次造成崩溃,并在第三次无声地覆盖完全不相关的内容。 发生以下哪种情况取决于操作系统(和操作系统版本),硬件,编译器(和编译器标志)以及系统上运行的其他所有内容。

这就是缓冲区超出错误的错误来源的原因:通常,生产中会出现明显的症状,但在调试器中运行时则不然; 并且症状通常不会出现在程序所在的部分。 当然,它们是一个受欢迎的漏洞,可以注入您自己的代码。

操作系统以一定的粒度分配在我的系统上, 页面大小为4kb(这在32位机器上是典型的),无论malloc()总是从操作系统获取新页面取决于您的C运行时库