当前位置: 首页 > 知识库问答 >
问题:

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

东门修能
2023-03-14

此问题旨在作为以下性质的所有常见问题的参考:

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

例如:

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

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

共有3个答案

卫博
2023-03-14

学习C语言时经常出现的一种情况是尝试使用单引号表示字符串文字:

char ptr[5];
strcpy(ptr, 'hello'); // crash here!
//            ^     ^   because of ' instead of "

在C语言中,'h'是一个单字符文本,而“h”是一个字符串文本,包含一个'h'和一个空终止符\0(即一个2字符数组)。 另外,在C语言中,字符文本的类型是int,也就是说,sizeof('h')等价于sizeof(int),而sizeof(char)1

char h = 'h';
printf("Size: %zu\n", sizeof(h));     // Size: 1
printf("Size: %zu\n", sizeof('h'));   // likely output: Size: 4
隆璞
2023-03-14

>

  • 指针仅指向内存位置。 您创建了一个指针,但尚未绑定到内存位置。 strcpy希望您传递两个指针(第一个不能是常量),它们指向两个字符数组,如以下签名:

    char * strcpy ( char * destination, const char * source );
    
    char* ptr = malloc(32);  
    strcpy(ptr, "hello world");
    
    char str[32];  
    strcpy(str, "hello world");
    

    您可以尝试以下代码段读取字符串,直到到达换行符(*您还可以添加其他空格字符,如“%[^\t\n]s”(制表符,换行符)或“%[^\t\n]s”(空格,制表符,换行符))。

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

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

  • 伯洋
    2023-03-14

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

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

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

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

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

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

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

    /*** 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");
    

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

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

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

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

    进一步阅读:

    指向无效数据的指针
    如何使用指针从其他函数访问局部变量?
    局部变量的内存是否可以在其作用域之外访问?

    分段错误和原因
    什么是分段错误?
    为什么写入以“char*s”而不是“chars[]”初始化的字符串时会出现分段错误?
    chars[]和char*s之间有什么区别?
    分段错误常见原因的明确列表
    什么是总线错误?

     类似资料:
    • 读取未初始化的变量会导致未定义的行为,例如 有人能给这个事实一个正式的解释吗?

    • 我目前正试图在android studio中创建一个日历应用程序。该应用包含一个具有不同“视图”的日历,例如月视图、周视图和日视图。 该应用程序使用片段作为页面,每个视图都是一个活动。 这是片段和按钮初始化每个视图的代码 在代码中显示日历月度视图的第一个按钮称为“Calendaractive”正常工作,但当单击显示日历每周视图的第二个按钮时,会导致应用程序崩溃并在logcat中给出以下错误 我不确

    • 我使用CameraX用例在屏幕上显示来自摄像头的图像,同时对其执行对象检测。下面是与CameraX相关的代码,位于我的主要活动的onCreate()函数中。 尽管如此,我在一些(比如说1/5)应用程序初始化时遇到了一个错误,在工作和非工作情况之间没有任何代码或二进制修改: 如果我尝试不访问previewView.display以避免崩溃,我只是得到空裁剪的图像,直到我重新启动应用程序。 它似乎与视

    • 这些是我的分级依赖项: 这是崩溃日志 致命异常:主进程:com.example.myapp,pid:16817 java.lang.nosuchmethoderror:LCOM/mapbox/services/android/telemetry类中没有虚拟方法初始化(Landroid/content/context;LJava/lang/string;LJava/lang/string;LCOM/

    • 我有下面的代码 每次我输入名字,然后点击回车,什么也没有发生我再次输入名字,什么也没有发生,我第三次输入名字,这里,它打印出来。第二个字符串也会出现同样的情况 我不明白会有什么问题。

    • 问题内容: 另一个链接的问题是在使用strcpy()时出现细分错误吗? 我有一个结构: 如何初始化指向上述类型结构的指针,以及如何初始化指向结构内部的10个字符串(incall [])的指针。 我首先初始化字符串,然后初始化结构。 谢谢。 编辑:我猜我用错了字,应该说分配。实际上,我将此结构作为线程的参数传递。线程数不是固定的,作为参数发送的数据结构对于每个线程都必须是唯一的,并且是“线程安全的”

    • 我有以下Java代码: 但是,当我运行它时,它会抛出以下错误: 我在do之前初始化了变量。while 循环,并在 try. 中设置值。捕获循环。似乎尚未设置该变量。抱歉,如果这是一个相当基本的问题,但我似乎无法弄清楚。

    • 我在尝试运行此程序时遇到以下异常。我正在使用在线编译器。甚至在读取字符串后尝试使用nextLine(),但没有成功。 我得到了以下异常:输入客户名称:在线程“main”java中输入客户id异常。util。NoSuchElementException:在java中找不到行。util。扫描仪。nextLine(Scanner.java:1585)位于Main。main(main.java:12)