【问题标题】:why segmentation fault (core dumped) show up at end为什么分段错误(核心转储)出现在最后
【发布时间】:2021-01-30 13:07:09
【问题描述】:

我不知道为什么这个分段会出现在我的输出末尾

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char** FileOpen(char *path );

int main(void)
{
char **lines =FileOpen("filename");
for(int i = 0 ; i < strlen(*lines) ; i++)
printf("%s\n",lines[i]);
    return 0 ; 
}
char** FileOpen(char *path)
{
    FILE * fileshow = fopen(path,"r");
    if(!fileshow)
    {
        printf("erorr trying open file %s",path);
        exit(1);
    }
    char**  lines = malloc(100 * sizeof( char* ));
    char buff[1000];
    int i = 0 ;
    while(fgets(buff,1000,fileshow))
    {
        //put null in end of str to show the end of string
        buff[strlen(buff)-1]= '\0';
        //geting string len to form the size of str
        int slen = strlen(buff);
        char *str = malloc(slen+1 * sizeof(char));
        //copy the string into the str
        strcpy(str,buff);
        
        lines[i]= str;
        i++;
    }
    return lines;
}

输出: 嘿,你好吗兄弟 嘿,你好吗兄弟 嘿哇 嘿,你好吗兄弟 嘿哇 嘿,所以 分段错误(核心转储)

【问题讨论】:

  • for(int i = 0 ; i &lt; strlen(*lines) ; i++) 看起来很可疑,lines 中没有 NULL
  • 与您的问题无关,但请记住基本算术优先级:slen+1 * sizeof(char) 实际上是 slen+(1 * sizeof(char))。在这种情况下,这并不重要,因为 sizeof(char) 被定义为始终1
  • 输出很奇怪,因为 printf 中有一个 \n 而输出没有。
  • strlen(*lines) 是第一行的长度。它不是文件中的行数。
  • 至于您的问题,请使用 调试器 来捕捉崩溃发生的时间,并在您的代码中找到它发生的位置..

标签: c segmentation-fault


【解决方案1】:

你必须做两件事:

由于函数FileOpen 中的lines 没有NULL 终止符,当您访问超出分配的内存的lines 是未定义的行为时,strlen 不会保存您,因为您正在访问无效的内存。
所以,

  1. FileOpen函数返回之前添加lines[i]= NULL;
char** FileOpen(char *path)
{
    /* your code */
    while(fgets(buff,1000,fileshow))
    {
       /* your code */
       i++;
    }
 lines[i]= NULL;
 return lines;
}

lines 打印时检查NULL,而不是使用strlen(*lines) 进行检查
2)在main函数中将for(int i = 0 ; i &lt; strlen(*lines) ; i++)替换为for(int i = 0 ;lines[i] != NULL; i++)

【讨论】:

  • @SergeBallesta,抱歉复制粘贴错误我的意思是lines[i]
  • 只是口味问题,但我发现lines[i] != NULL 更易于阅读。当然,现在完全正确……
【解决方案2】:

这个sn-p代码有很多问题...

  1. malloc 缺少 free(..).. 无处释放内存.. 所以内存泄漏。

  2. 打开的文件没有关闭..

  3. strlen() 将搜索 0。如果在前 1000 个中没有找到它,它将继续搜索直到找到一个,然后它会在该位置 (place-1) 上写入 0... 这可能是任何地方..这可能是段错误..即使在您的内存空间之外读取也可能触发段错误..

  4. fgets() 将返回一个以空字符结尾的字符串,因此您无需手动添加它..

  5. 您分配了 100 行。如果文件较少,您仍在尝试打印 100 行。并且这些指针没有设置。您正在从随机内存位置打印并触发段错误..

【讨论】:

  • 当您说“strlen() 将搜索 0。如果在前 1000 个中没有找到,它将继续搜索...”可能看起来有点误导,因为您没有说你从哪里得到那个号码1000。您应该说它是其中一个数组的大小。但是由于它以正确的大小传递给fgets,因此如果fgets 成功,则保证数组具有空终止符。
  • 是的.. 3 和 4 是互斥的.. 我把它放在三个中,所以发布问题的人下次会考虑 strlen,当他使用 smthg 而不是 fgets 时......跨度>
猜你喜欢
  • 1970-01-01
  • 2017-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多