为什么以下工作并没有抛出某种分段错误?
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”)?
提前非常感谢你!
答案 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运行时库。