尝试执行茎文件时出现分段错误(核心转储)

Posted

技术标签:

【中文标题】尝试执行茎文件时出现分段错误(核心转储)【英文标题】:Segmentation fault (core dumped) while trying to execute the stem file 【发布时间】:2021-12-20 19:42:51 【问题描述】:

我有一个名为myfile 的stem 文件,它有2 个子文件:myfile.datamyfile.names

现在我想写一个代码,它首先检查.names文件的最后一行,看看是否有零,如果有任何其他数字不是零,那么它会说noisy data。如果 .names 文件的最后一行为零,那么我需要读取 .data 文件并对 .data 文件执行一些操作以产生有效的输出。

现在我在下面给出我尝试做的事情:

int main(int argc, char **argv)

                char* path;
                sprintf(path, "%s.names", argv[1]);
                printf("...%s...\n", path);
                //FILE *fp =stdin;
                fp = fopen(path, "r");
                
                char buff[1024];
                int check = 0;

                fseek(fp, 0, SEEK_SET);

                while(!feof(fp))
                
                    memset(buff, 0x00, 1024);
                    fscanf(fp, "%[^\n]\n", buff);
                
                
                if(strchr(buff, '0') != NULL)
                    check = 1;
                
                
                if(check == 0)
                    printf("Noisy data...\n");
                
                
                else if(check == 1)
                    
                    char* path1;
                    sprintf(path1, "%s.data", argv[1]);
                    printf("...%s...", path1);
                    //FILE *fp1 = stdin;
                    fp1 = fopen(path1, "r");
                    
                    char buf[1024];
                
                    if( fgets(buf, sizeof buf, fp1) == NULL )
                        fputs("Input error\n", stderr);
                        return 1;
                    
                    ...
                    ...
                    Produces the perfect output

编译成功。

执行此操作:<./executable_filename> <stemFileName> > <outputFileName>

所以每当我在做的时候:./myFileName myfile output。它说Segmentation fault (core dumped)。为什么会这样?

还有一点,我的 .names 文件将包含:| Final Pseudo Deletion Count is 0.| Final Pseudo Deletion Count is 1.| Final Pseudo Deletion Count is 2. ,所以我想 strchr 会完成我的工作吗?

我最初尝试修改以下代码,但尝试了几种不同的方法后,我无法做到。

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

FILE * xfopen(const char *path, const char *mode);
void * xmalloc(size_t s);

void parse_line(const char *buf, int *max, int column_count)

    for(int i = 0; i < column_count; i++ )
        char *end;
        int t = strtol(buf, &end, 10);
        
        if( t > max[i] )
            max[i] = t;
        
        
        if( !((i < column_count - 1 && *end == ',') || (i == column_count - 1 && *end == '\n')) )
            fprintf(stderr, "invalid input '%c' in %s", *end, buf);
            exit(1);
        
        buf = end + 1;
    


int main(int argc, char **argv)


    char *path1;
    char *path = argc > 1 ? argv[1] : "stdin";
    
    sprintf(path, "%s.data", argv[1]);
    
    FILE *in = argc > 1 ? xfopen(path, "r") : stdin;
    
    char buf[1024];
    int column_count = 1;
    int row_count = 1;
    int *max;

    /* Read first line to determine number of columns */
    if( fgets(buf, sizeof buf, in) == NULL )
        fputs("Input error\n", stderr);
        return 1;
    

    for( const char *p = buf; *p; p++ )
        if( *p == ',' )
            column_count += 1;
        
    
    
    max = xmalloc(column_count * sizeof *max);
    
    for( int i = 0; i < column_count; i++ )
        max[i] = INT_MIN;
    
    
    parse_line(buf, max, column_count);
    while( fgets(buf, sizeof buf, in) != NULL )
        row_count += 1;
        parse_line(buf, max, column_count);
    
    
    if( fseek(in, 0L, SEEK_SET) )
        perror(path);
        return 1;
    
    
    printf("%d %d ", row_count, column_count - 1);
    
    for( int i = 0; i < column_count - 1; i += 1 )
        printf("%d ", max[i]);
    
    
    printf("%d\n", max[column_count - 1] + 1);

    while( fgets(buf, sizeof buf, in) != NULL )
        char *comma = strrchr(buf, ',');
        if( comma == NULL )
            fprintf(stderr, "Invalid input\n");
            return 1;
        
        
        *comma = '\0';
        int k = strtol(comma + 1, NULL, 10);
        for(char *p = buf; *p;  p++)
            if( *p == ',' ) *p = ' '; 
        
        printf("%s %d\n", buf, k + 1);
    


FILE *
xfopen(const char *path, const char *mode)

    FILE *fp = path[0] != '-' || path[1] != '\0' ? fopen(path, mode) :
        *mode == 'r' ? stdin : stdout;
    if( fp == NULL )
        perror(path);
        exit(EXIT_FAILURE);
    
    
    return fp;


void *
xmalloc(size_t s)

    void *rv = malloc(s);
    if( rv == NULL )
        perror("malloc");
        exit(EXIT_FAILURE);
    
    return rv;

【问题讨论】:

【参考方案1】:

几个错误立即显而易见:

                char* path;
                sprintf(path, "%s.names", argv[1]);

传递给sprintf 的缓冲区必须指向可写内存,但path 未初始化并且没有特别指向任何地方。见Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer。您可能希望 path 成为数组而不是指针。

如果您启用警告,您的编译器可以警告您有关此类错误的许多错误,例如与gcc -Wall -O。这会节省你问这个问题的时间(和我回答这个问题的时间)。 Why should I always enable compiler warnings?

此外,由于您无法控制字符串argv[1] 的长度,因此缓冲区的固定长度永远不会足够长,因此您可能希望使用snprintf 来防止缓冲区溢出。请参阅understanding the dangers of sprintf(...)(适用于 C++,但解决了相同的问题)。

path1 更下方也有同样的问题。

fp = fopen(path, "r");

fopen 如果失败,将返回 NULL,而你永远不会检查这一点。在这种情况下,您的程序会出现段错误。 fp1 也有同样的问题。

while(!feof(fp))

这是always wrong。

fscanf(fp, "%[^\n]\n", buff);

sprintf 类似的溢出风险。此外,您必须检查fscanf 是否成功;这是检查文件结尾的正确方法,代替错误的while (!feof(fp))

if( fgets(buf, sizeof buf, fp1) == NULL )
                        fputs("Input error\n", stderr);
                        return 1;

fgets 返回 NULL 不一定表示“输入错误”;可能只是到达了文件的末尾。


有关分段错误的原因以及如何调试它们的一般信息,另请参阅

What is a segmentation fault?

Definitive List of Common Reasons for Segmentation Faults

What is a debugger and how can it help me diagnose problems?

【讨论】:

非常感谢您的帮助。但是我正在尝试纠正和纠正代码,但我无法做到,因为我对 C 很陌生。如果我给出我尝试修改的初始代码,请你帮帮我!我只想修改代码,它将首先检查.names文件的最后一行,看看是否有零,如果除了zero之外还有其他数字,那么它会说noisy data。如果.names 文件的最后一行为零,那么我需要读取.data 文件并对该.data 文件进行一些操作以生成valid output. 我在下面发布我的代码。 @Dev:没有一种简单的方法可以只读取文件的最后一行,请参阅***.com/questions/29884493/…。您通常只需阅读整篇文章,然后回想一下最后一行。

以上是关于尝试执行茎文件时出现分段错误(核心转储)的主要内容,如果未能解决你的问题,请参考以下文章

尝试声明大数组时出现分段错误和核心转储[重复]

访问共享进程内存时出现分段错误(核心转储)

在opencv c ++中查找图像卷积时出现分段错误(核心转储)错误

我运行程序时出现“分段错误(核心转储)”

使用 pthread_create 时出现“分段错误(核心转储)”

当我在 ubundu12.04 中运行“phantomjs”命令时出现分段错误(核心转储)