1

运行以下代码时,我的程序意外崩溃!

#include<stdio.h>
#include<string.h>

int main(){

    char *str = NULL;
    strcpy(str, "swami");
    printf("%s", str);
    return 0;
}

但如果我这样做:

#include<stdio.h>
#include<string.h>

int main(){

    char *str;
    strcpy(str, "swami");
    printf("%s", str);
    return 0;
}

此代码工作正常并生成正确的输出!

我正在使用 gcc 编译器(代码块 IDE)。此外,这两个代码都会导致 DevCpp 中的程序崩溃。谁能解释一下为什么会这样!?

4

5 回答 5

23

您不能写入NULL指针。

在第二种情况下,您的指针被随机初始化到程序内存中的有效位置。这就是为什么你可以做一个strcpy

将两个程序都更改为

str = malloc(size)

或.calloc之前的选项strcpy。(size是您要保留的空间大小。)

根据评论,您还可以将声明更改strchar str[6](或更多)。

最后编辑:我将向您展示这张显示程序内存和指针的图片:

在此处输入图像描述

灰色区域和红色区域是禁止的(您不能从它们写入或读取;顶部的灰色区域用于内核内存,而其他区域是尚未回收的空间)。底部的红色区域是特殊的 0 页面。因为你的NULL意志指向这一点,你的程序就会失败。0str = NULL

如果你不分配任何东西,str它最终会随机指向。它仍然可以指向红色区域或灰色区域->您的程序将失败。它可以指向绿色或蓝色(两种色调)区域,使您的程序工作(除了它指向只读位置并且您写入它的情况)。为指针分配区域使其指向绿色区域,将其放大到顶部。

另一个选项,str[6]将堆栈区域扩大到底部。所有局部变量都在堆栈中保留空间,而用 ,malloc和其他朋友分配的所有空间都进入堆。realloccalloc

最后,看看一篇关于和之间区别的博客文章char[]char *

PS:如果您想使用 GNU 扩展,您可以查看该asprintf功能。它会为一个字符串分配空间并在那里写一些内容:

asprintf(&str, "swami");

或者

asprintf(&str, "%d + %d == %d\n", 1, 2, 3);

但是,如果你想要便携性,你会远离这个功能。

于 2012-09-18T18:02:54.607 回答
4

在这两个版本中,您都没有分配内存来将字符串复制到,因此两者都会调用未定义的行为。第一个崩溃是因为您明确初始化strNULL,因此strcpy取消引用了一个NULL在大多数系统上崩溃的指针。第二,str指向任意内存,取消引用未初始化的指针可能会或可能不会崩溃。

于 2012-09-18T18:05:08.740 回答
2

因为在. NULL_ 因此,您尝试写入使程序崩溃的无效内存地址。#define NULL ((void *)0)<stdlib.h>

于 2012-09-18T18:51:39.107 回答
1

阅读此链接

//destination =Pointer to the destination array where the content is to be copied.
char * strcpy ( char * destination, const char * source );

您将目标设置为 NULL,因此您尝试将源复制到 NULL。这就是它崩溃的原因。您应该留出一些内存来将字符串复制到。

int main(){
      char *str=malloc(6);  //enough for "swami"+'\0'
      strcpy(str, "swami");
      printf("%s", str);
      return 0;

}

于 2012-09-18T18:06:26.477 回答
1

strcpy只是复制,而不是为它生成空间。

在第一种情况下,您尝试将字符串写入代码段的开头:这不是一个好主意。

在第二种情况下,您开始将字符串写入某个地方,并且在您的情况下并没有因为运气和编译器的帮助而崩溃。

您应该执行以下操作之一:

一种。分配内存:str = new char[10]
B。使用strdup女巫将字符串复制到新位置。

于 2012-09-18T18:07:52.000 回答