数据复制/扫描/读取到未初始化的指针时发生崩溃或“分段错误”

这个问题的目的是作为参考所有常见问题的性质:

当我将数据复制/扫描到未初始化的指针指向的地址时,为什么会出现神秘的崩溃或“分段错误”?

例如:

char* ptr; strcpy(ptr, "hello world"); // crash here! 

要么

 char* ptr; scanf("%s", ptr); // crash here! 

指针是一种特殊types的variables,它只能包含另一个variables的地址。 它不能包含任何数据。 你不能“复制/存储数据到指针” – 这是没有任何意义的。 你只能设置一个指向指向别处分配的数据的指针。

这意味着为了使指针有意义,它必须始终指向有效的内存位置。 例如,它可以指向在堆栈上分配的内存:

 { int data = 0; int* ptr = &data; ... } 

或在堆上dynamic分配内存:

 int* ptr = malloc(sizeof(int)); 

在初始化之前使用指针总是一个bug。 它还没有指向有效的记忆。

这些例子都可能导致程序崩溃或其他types的意外行为,如“分段错误”:

 /*** examples of incorrect use of pointers ***/ // 1. int* bad; *bad = 42; // 2. char* bad; strcpy(bad, "hello"); 

相反,您必须确保指针指向(足够)分配的内存:

 /*** examples of correct use of pointers ***/ // 1. int var; int* good = &var; *good = 42; // 2. char* good = malloc(5+1); // allocates memory for 5 characters and 1 terminator strcpy(good, "hello"); 

请注意,您也可以设置一个指针指向一个定义良好的“无处”,让它指向NULL 。 这使得它成为一个空指针 ,这是一个指针,保证不指向任何有效的内存。 这与将指针完全未初始化完全不同。

 int* p1 = NULL; // pointer to nowhere int* p2; // uninitialized pointer, pointer to "anywhere", cannot be used yet 

但是,如果试图访问空指针指向的内存,则可能会遇到与使用未初始化的指针类似的问题:崩溃或分段错误。 在最好的情况下,你的系统注意到你试图访问地址null,然后抛出一个“空指针exception”。

空指针exception错误的解决scheme是相同的:在使用它之前,必须将指针设置为指向有效内存。


进一步阅读:

指向无效数据的指针
如何使用指针从不同的函数访问本地variables?
局部variables的内存是否可以在其范围外访问?

分割错误和原因
什么是分段错误?
为什么在写入用“char * s”初始化而不是“char s []”的string时会出现分段错误?
char s []和char * s有什么区别?
分割故障常见原因的确定清单
什么是巴士错误?

  1. 指针只指向一个内存位置。 您创build了一个指针,但尚未绑定到内存位置。 strcpy希望你传递两个指针( 第一个不能是常量 ),指向这个签名的两个字符数组:

     char * strcpy ( char * destination, const char * source ); 

    样本用法:

     char* ptr = malloc(32); strcpy(ptr, "hello world"); 
     char str[32]; strcpy(str, "hello world"); 
  2. 您可以尝试下面的代码片段来读取string,直到到达换行符(*还可以添加其他空白字符,如"%[^\t\n]s"tab,newline )或"%[^ \t\n]s"空格,制表符,换行符 ))。

     char *ptr = malloc(32); scanf("%31[^\n]", ptr); 

    (在现实生活中,不要忘记检查scanf()的返回值!)