【问题标题】:Segmentation Fault? Why?分段故障?为什么?
【发布时间】:2014-08-24 11:57:18
【问题描述】:

不知道为什么这段代码显示Segmentation Fault。下面是代码

int main()
{   
    char *str;
    printf("\nEnter a string - \n");
    scanf("%s",str);
    printf("%s\n",str);
}

分段错误的原因可能是什么? 另外我想知道为什么在 Linux 中使用gets()function 很危险?

【问题讨论】:

  • 提示:str 指向哪里?
  • gets() 很危险,因为它可能导致缓冲区溢出,而不仅仅是在 Linux 上。
  • 考虑使用getline(3)char *buf=NULL;size_t siz=0; 然后ssize_t len = getline(&buf,&siz,stdin);
  • 你为什么不赞成这个问题??
  • 可能是因为您的第一个问题(使用str uninitialized)是一个非常基本的问题,每个 C 教程都涵盖了该问题,因此此处偏离主题。第二个问题(关于gets)缺乏研究工作。

标签: c linux segmentation-fault


【解决方案1】:

首先,您可能需要知道您可以使用char str[40] = {0};(编译时内存分配)。

由于您提出了一个有关动态内存分配的问题,因此您应该在尝试存储任何内容之前将内存分配给指针。因为指针可能指向任何随机位置(野指针),因此您可能会尝试访问不打算访问的内存,这会导致段错误。

int main()
{   
    char *str;
    str = malloc(sizeof(char) * 40); // allocate memory where str will be pointing,here i allocate 40 bytes
    printf("\nEnter a string - \n");
    scanf("%39s",str);
    printf("%s\n",str);
    free(str); //important to release the memory!
}

回答你的第二个问题,gets() 在任何平台上都是危险的,因为它可能导致缓冲区溢出。

考虑一个场景,您尝试填充超出其容量的缓冲区:

char *buff = malloc(sizeof(char)*10);
strcpy(buff, "This String Will Definitely Overflow the Buffer Because It Is Tooo Large");

如您所见,strcpy() 函数会将完整的字符串写入 'buff',但由于 'buff' 的大小小于字符串的大小,因此数据将被写入数组的右边界'buff'。现在,根据您使用的编译器,很有可能在编译过程中不会注意到这一点,并且在执行过程中也不会崩溃。原因很简单,内存属于程序,因此内存中的任何缓冲区溢出都可能被忽视。

所以在这种情况下,缓冲区溢出会悄悄地破坏相邻的内存,如果损坏的内存正在被程​​序使用,那么它可能会导致意想不到的结果。

安全解决方法:

char *buf=NULL; 
size_t siz= 30; 
ssize_t len = getline(&buf,&siz,stdin);

这是一种解决方法吗?好吧,您应该阅读更多关于getline() 的信息。

【讨论】:

  • 使用scanf("%39s", str);会更安全
  • 关于%39s 的部分很重要,因为OP 很可能将gets 替换为scanf 以消除可能的缓冲区溢出,但scanf("%s",str) 具有与gets 完全相同的漏洞
  • @SamDunk 既然他是初学者,为什么不从没有可怕错误的代码开始。你说gets 很糟糕,但是你的代码有效地执行了getsgetsscanf("%s" 相同,除了scanf 在所有空白处停止)这也是not cast malloc 的好时机,在2014 年无需复制需要此演员阵容的 1970 年代书籍
  • @MattMcNabb 先生,我已经进行了必要的更改。感谢您指出:)
  • 超级解释!
猜你喜欢
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
相关资源
最近更新 更多