C语言中,当尝试将数据复制、扫描或读取到未初始化的指针时,程序崩溃或发生段错误(Segmentation Fault)的原因。这种错误在C语言中非常常见,主要是由于指针在使用前没有正确地分配内存。

1、问题背景

C语言中,指针是一种存储内存地址的变量。要正确地使用指针,通常需要创建一个指针变量,将指针指向一块有效的内存区域,通过指针访问或修改这块内存区域中的数据。如果在未分配内存时就尝试使用指针,会导致程序崩溃或产生段错误,因为它试图访问的地址是无效的或未授权的。

2、常见错误和示例

1)未初始化指针的使用

如声明了一个指针,但没有分配内存就直接使用它,那么这个指针会指向一个随机的内存地址,可能是未授权的地址区域。

#include <stdio.h>

int main() {
    int *ptr;  // 只声明指针,但未分配内存

    *ptr = 10;  // 试图向未初始化的指针指向的内存写入数据,会导致段错误

    return 0;
}

注意:ptr 是一个未初始化的指针,它指向一个随机的内存地址。试图将 10 写入这个地址会导致段错误。

解决方法:

保在使用指针前为其分配内存。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)malloc(sizeof(int));  // 分配内存

    if (ptr == NULL) {
        perror("Memory allocation failed");
        return 1;
    }

    *ptr = 10;  // 现在可以安全地使用指针
    printf("Value: %d\n", *ptr);

    free(ptr);  // 释放分配的内存
    return 0;
}

2)未为指针分配数组内存

当需要将数据存储到指针指向的数组中时,必须确保已经为数组分配了足够的内存。如果没有分配内存,程序可能会崩溃。

#include <stdio.h>

int main() {
    char *str;

    // 错误:直接将字符串写入未分配内存的指针
    scanf("%s", str);  // 如果输入较长,会导致段错误

    return 0;
}

注意:str 只是一个指向 char 的指针,没有指向任何有效的内存地址。scanf 试图将输入内容存储到 str 指向的地址中时,会导致段错误。

解决方法:

分配足够的内存以存储字符串。

#include <stdio.h>
#include <stdlib.h>

int main() {
    char *str = (char *)malloc(100 * sizeof(char));  // 分配 100 个字符的内存

    if (str == NULL) {
        perror("Memory allocation failed");
        return 1;
    }

    printf("Enter a string: ");
    scanf("%99s", str);  // 限制输入长度,避免缓冲区溢出

    printf("You entered: %s\n", str);

    free(str);  // 释放分配的内存
    return 0;
}

3)释放后继续使用指针(悬空指针)

当使用 free() 释放了指针指向的内存后,继续通过这个指针访问内存,就会导致悬空指针问题。

#include <stdio.h>
#include <stdlib.h>

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

    if (ptr == NULL) {
        perror("Memory allocation failed");
        return 1;
    }

    *ptr = 10;
    printf("Value before free: %d\n", *ptr);

    free(ptr);  // 释放内存

    printf("Value after free: %d\n", *ptr);  // 悬空指针,未定义行为

    return 0;
}

注意:free() 释放了 ptr 所指向的内存后,ptr 仍然持有这块已经被释放的地址。继续使用 ptr 会导致未定义行为。

解决方法:

在释放内存后将指针置为 NULL,这样可以避免误操作。

#include <stdio.h>
#include <stdlib.h>

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

    if (ptr == NULL) {
        perror("Memory allocation failed");
        return 1;
    }

    *ptr = 10;
    printf("Value before free: %d\n", *ptr);

    free(ptr);  // 释放内存
    ptr = NULL; // 将指针置为 NULL

    return 0;
}

推荐文档