当数据复制/扫描/读取到未初始化的指针时崩溃或 "segmentation fault"

标签 c pointers segmentation-fault

此问题旨在作为所有常见问题的引用:

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

例如:

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

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

最佳答案

指针是一种特殊类型的变量,它只能包含另一个变量的地址。它不能包含任何数据。您不能“将数据复制/存储到指针中” - 这没有任何意义。您只能设置一个指针来指向其他地方分配的数据。

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

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

或者在堆上动态分配的内存:

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

在初始化之前使用指针始终是一个错误。它尚未指向有效的内存。

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

/*** 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*  the null terminator
strcpy(good, "hello");
<小时/>

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

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

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

空指针异常错误的解决方案是相同的:在使用指针之前必须将其设置为指向有效内存。

<小时/>

进一步阅读:

指向无效数据的指针
How to access a local variable from a different function using pointers?
Can a local variable's memory be accessed outside its scope?

段错误及原因
What is a segmentation fault?
Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?
What is the difference between char s[] and char *s?
Definitive List of Common Reasons for Segmentation Faults
What is a bus error?

关于当数据复制/扫描/读取到未初始化的指针时崩溃或 "segmentation fault",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45893755/

相关文章:

c++ - COM 指针和进程终止

c++ - 后增量运算符重载中的指针

c++ - 使用递归函数时出现段错误

C:将带有字符串的结构复制到共享内存

c - How to compile nanopb .proto file into .h and .c files using nanopb and protobuf (`protoc` 编译问题)

c - 如何限制 Xlib 图形基元绘制的表面?

c++ - 我无法标记我的角色,我该如何到达那里?

c - 未在指针给定的地址处显示正确的值

c - 使用指向数组的结构体进行队列

c - 从当前目录获取文件名,保存到 char ** array, glob, C, seg fault