所以我有一些C代码:
#include#include /* putting one of the "char*"s here causes a segfault */ void main() { char* path = "/temp"; char* temp; strcpy(temp, path); }
这样编译,运行和行为就像它看起来一样.但是,如果将一个或两个字符指针声明为全局变量,则strcpy会导致分段错误.为什么会这样?显然我对范围的理解有误.
正如其他海报所提到的,问题的根源在于临时未初始化.当在堆栈上声明为自动变量时,它将包含该内存位置中发生的任何垃圾.显然,对于正在运行的编译器+ CPU + OS,该位置的垃圾是一个有效的指针.strcpy"成功",因为它不会发生段错误,但实际上它将字符串复制到内存中其他位置的任意位置.这种内存损坏问题引起了各地C程序员心中的恐惧,因为它非常难以调试.
将临时变量声明移动到全局范围时,它将被置于BSS部分并自动归零.尝试取消引用*temp然后导致段错误.
将*path移动到全局范围时,*temp会向上移动堆栈上的一个位置.该位置的垃圾显然不是有效指针,因此取消引用*temp会导致段错误.
temp变量不指向任何存储(内存),并且它未初始化.
如果temp被声明为char temp[32];
那么代码无论在何处被声明都可以工作.但是,像这样用固定大小来声明temp还有其他问题,但这是另一天的问题.
现在,为什么在全局声明而不是本地声明时会崩溃.运气...
在本地声明时,temp的值来自当时堆栈上可能存在的值.幸运的是,它指向一个不会导致崩溃的地址.然而,它正在摧毁其他人使用的内存.
全局声明时,在大多数处理器上,这些变量将存储在将使用需求零页的数据段中.因此char *temp
看起来好像是宣布的char *temp=0
.
你忘了分配和初始化temp:
temp = (char *)malloc(TEMP_SIZE);
只要确保TEMP_SIZE足够大.你也可以在运行时计算它,然后确保大小足够(至少应该是strlen(path))