无效的读/写有时会产生分段错误,有时不会

示例代码:

int main () { char b[] = {"abcd"}; char *c = NULL; printf("\nsize: %d\n",sizeof(b)); c = (char *)malloc(sizeof(char) * 3); memcpy(c,b,10); // here invalid read and invalid write printf("\nb: %s\n",b); printf("\nc: %s\n",c); return 0; } 

在代码中看到我已经做了一些无效的读取和无效的写入,但是这个小程序工作正常,不会创buildcore dump

但是一旦在我的大型图书馆里,每当我做了1个字节的无效读取或无效写入,它总是在创build核心转储。

题:

为什么我有时会从无效读/写中获得核心转储,有时不会获得核心转储?

Solutions Collecting From Web of "无效的读/写有时会产生分段错误,有时不会"

你要做的是基本上缓冲区溢出&在你的代码示例更具体的堆溢出 。 你只是偶尔看到崩溃的原因取决于你正在访问哪个内存区域,以及你是否有权访问/写入(Dan Fego已经很好地解释了这个问题)。 我觉得Dan Fego提供的例子更多的是关于堆栈溢出(更正欢迎!)。 gcc具有与堆栈上的缓冲区溢出相关的保护(堆栈粉碎)。 你可以在下面的例子中看到这个(基于堆栈溢出):

 #include <stdio.h> #include <string.h> int main (void) { char b[] = { "abcdefghijk"}; char c [8]; memcpy (c, b, sizeof c + 1); // here invalid read and invalid write printf ("\nsize: %d\n", sizeof b); printf ("\nc: %s\n", c); return 0; } 

示例输出:

 $ ./a.out size: 12 c: abcdefghi    *** stack smashing detected ***: ./a.out terminated 

这个保护可以使用gcc中的-fno-stack-protector选项来禁用。
缓冲区溢出是安全漏洞的主要原因之一。 不幸的是像memcpy这样的函数不会检查这些类型的问题,但有办法来防止这类问题。
希望这可以帮助!

这完全取决于您在执行无效读/写操作时覆盖或取消引用的内容。 具体来说,如果覆盖了一些被取消引用的指针,比如说,一个最重要的字节,那么最终可能导致某些内容被完全不同(完全无效)的区域解除引用。

所以,例如,如果堆栈被安排成memcpy超过c的末尾将会覆盖b一部分,当你试图用b作为参数调用printf()时,它会尝试去取指针并解引用它来打印一个串。 由于它不再是一个有效的指针,这将导致段错误。 但是由于像堆栈安排这样的东西是依赖于平台的(也许是编译器),所以在不同的程序中可能看不到类似的例子。

你创建一个3个字符串c ,但是你拷贝了10个字符。 这是一个错误。

它被称为缓冲溢出:你写在一个不属于你的内存中。 所以行为是不确定的。 它可能是一个崩溃,它可以正常工作,或者它可以修改你创建的另一个变量。

所以要做的事情就是为c分配足够的内存来包含b的内容:

 c = (char *)malloc(sizeof(char) * (sizeof(b)+1)); // +1 is for the '\0' char that ends every string in c. 

2 – 当你在c复制b不要忘记把字符串char: '\0'的结尾。 在C标准中是强制性的。 所以printf("%s",c); 知道在哪里串完成。

3 – 你从b复制了10个字符到c但只包含5个字符(a,b,c,d和'\ 0'),所以memcpy的行为是不确定的(例如:memcpy可以尝试读取不能读,…)。

你只能复制你自己的内存: b的5个字符。

4 – 我认为定义b的好方法是: char b="abcd";char b={'a','b','c','d',0};