【问题标题】:Segmentation fault: Using strtok, system calls. C programming分段错误:使用 strtok,系统调用。 C 编程
【发布时间】:2019-02-02 08:15:12
【问题描述】:

我目前正在尝试 strtok 两次,以便标记文件传递的所有命令。第一轮标记化有效,但随后出现分段错误。可能是什么?我试图使所有数组更小,因为我认为这是一个内存问题。这也是用 C 编写的,我没有收到任何错误或警告。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>

int main(int argc, char *argv[])
{
        char content[100];
        int fd;
        ssize_t bytes = 0;
        fd = open(argv[1], O_RDONLY);
        int i = 0;

        char* token;
        const char a[2] = "\n";
        const char b[2] = " ";
        char storage[20][20];
        char temp[20][20];
        bytes = read(fd, content, sizeof(content)-1);
        close(fd);

        if(fd < 0)
        {
                write(1, "File doesn't exist\n", 19);
                return 1;
        }


        token = strtok(content, a);
        strcpy(storage[0],token);
        printf("%s\n",storage[0]);

        while(token != NULL)
        {
        i++;
        token = strtok(NULL, a);
        strcpy(storage[i],token);
        printf("%s\n",storage[i]);
        }

      token = strtok(storage[0],b);
        strcpy(temp[0], token);
        printf("%s\n",temp[0]);
        i = 0;

        while(token != NULL)
        {
        i++;
        token = strtok(NULL, b);
        strcpy(temp[i],token);
        printf("%s\n",temp[i]);

        }





return 0;

}

这是我得到的输出:

/bin/ls -l 
/bin/cat command.txt 
/usr/bin/wc -l -w command.txt 
??
Segmentation fault

【问题讨论】:

  • 调试器是你的朋友。
  • 这段代码明显坏了。您调用strtok,然后盲目地假设它成功并使用其结果指针作为常规strcpy 的源。只有稍后您才会测试NULL 的令牌结果。同样的问题存在于循环内外的多个地方。想想看:strtok 可以返回 NULL。那么.. 在调用strtok 和使用它的结果之间,您在哪里检查?
  • 文件有多少行?还有我每行的许多令牌?行数超过 20 行和行数超过 20 的文件,会使你的程序访问不属于进程的内存。
  • @WhozCraig 我在每个命令后添加了打印行。它似乎可以正确输出,但由于某种原因,它总是比预期的迭代次数多一次,这使得它打印出随机值。
  • @vmaroli 大约 71 行,如果是这种情况,我该如何解决?

标签: c segmentation-fault system system-calls strtok


【解决方案1】:
    strcpy(storage[0],token);
    printf("%s\n",storage[0]);

您在 4 或 5 次中执行相同操作。您需要检查 token 是否不为 NULL。否则你的程序只是UB

if( token)
{
    strcpy(storage[0],token);
    printf("%s\n",storage[0]);
}
else
{
    /* do something if token is NULL */
}

您还可以重新组织循环(以第一个循环为例):

    token = strtok(content, a);
    i = 0;

    while(token != NULL)
    {
    strcpy(storage[i],token);
    printf("%s\n",storage[i++]);
    token = strtok(NULL, a);
    }

【讨论】:

  • 这是第一个strtok,然后我说while(token!= NULL),这是否会通过检查token是否不为NULL?
  • @beatsbyse 我害怕,拿笔和纸按照程序流程进行操作。您的 while 条件不能保护您免受 NULL 指针取消引用。
【解决方案2】:

当您的程序尝试访问超出分配给程序的内存区域时,会发生分段错误。由于您只分配了大小为 20 的数组用于存储和存储更多,这是一个问题。此外,您还分配了大小为 20 的数组来存储每行的令牌,这可能还不够,具体取决于每行的令牌数量。除此之外,像其他人提到的那样,您还需要检查 strtok 是否返回 null。尝试取消对空指针的引用也会导致分段错误

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多