Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
比malloced写更多的字符。为什么它没有失败?_C_Memory Management_Segmentation Fault_Memory Alignment_Strcat - Fatal编程技术网

比malloced写更多的字符。为什么它没有失败?

比malloced写更多的字符。为什么它没有失败?,c,memory-management,segmentation-fault,memory-alignment,strcat,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, p

为什么下面的工作并没有抛出某种分割错误

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的内存之后的内存可用性

另外,当你想随机选择时,你不应该加引号。那应该是

strcat(newPath, random);

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

你打这个电话很幸运。您不会得到segfault,因为您的呼叫可能会停留在分配的地址空间中。这是未定义的行为。写入内容的最后一个字符不能保证不被覆盖。此调用也可能失败。

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

缓冲区溢出不一定会导致segfault。这种行为根本没有定义。您可能会在一次写入不属于您的内存时侥幸逃脱,在另一次导致崩溃,并在第三次无声地覆盖完全无关的内容。发生哪种情况取决于操作系统(和操作系统版本)、硬件、编译器(和编译器标志),以及系统上运行的几乎所有其他内容


这就是为什么缓冲区溢出是如此令人讨厌的bug来源:通常,明显的症状会在生产中出现,但在通过调试器运行时不会出现;这些症状通常不会出现在节目的起始部分。当然,它们是一个很受欢迎的漏洞,可以插入您自己的代码。

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

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

但是,正如其他人所说,未定义的行为并不意味着您的程序将崩溃。这只意味着它可以做任何事情(包括撞车,但如果你运气不好,也不能撞车)


(另外,不应强制转换
malloc()
的返回值)

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

这可不幸运。相反,这意味着您破坏了其他有价值的数据(可能是内部
malloc
簿记),这将导致程序执行后期出现错误行为(最坏情况:安全漏洞或大量数据丢失)。幸运的是,如果程序崩溃了,那么你会立即知道有一个bug,而没有其他东西被破坏……一些除虫器会在那里崩溃。当然,lucky的意思是这些调用没有出错,因为它们不能出错,而是因为例如,页面被分配了存储额外字节的位置。我知道原因。我只是认为“不崩溃”是不吉利的(危险的)可能性,“崩溃”是幸运的。如果内存溢出确实导致程序爆炸,那将是难以置信的——想想找到它们是多么容易!当您可以分配n个字节并写入n+1个字节,并且在100次中99次没有看到不良影响时,很难找到问题。@graeme 100%同意。这就是为什么在C语言中,程序员应该特别小心,非常小心,非常小心organized@graeme当前位置如果你喜欢那种行为,你应该调查一下。自述文件:Electric Fence是另一种malloc()调试器。它使用系统的虚拟内存硬件来检测软件何时超出malloc()缓冲区的边界。它还将检测free()释放的任何内存访问。由于它使用VM硬件进行检测,Electric Fence会在第一条导致边界冲突的指令上停止您的程序。为什么不强制转换
malloc
的返回值?@Graeme:请参阅“确定”,感谢链接。我知道在C语言中这是不必要的,但我从未想过这是一个坏主意。为什么我要假设第一个字节设置为0?不明白。@pewpew,
strcat(newPath,path)
假设
newPath
是一个以null结尾的字符串。由于
newPath
malloc()的返回值
将起作用。)