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

时间:2011-07-16 15:42:02

标签: c memory-management segmentation-fault memory-alignment strcat

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

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”)?

提前非常感谢你!

9 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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

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

strcat(newPath, random);

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

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

答案 8 :(得分:0)

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