【问题标题】:Segmentation Fault when copying content from argv[] to a char*将内容从 argv[] 复制到 char* 时出现分段错误
【发布时间】:2020-12-12 14:41:51
【问题描述】:

我看到了一些关于这类问题的问题,但到目前为止都没有帮助。

代码在控制台上运行良好,但调试器告诉我在main 上为指针*word 分配内存时发生了分段错误,就在包含switch 语句的while 之后。它说argv[optind] 指向NULL,我认为它是因为在调试期间它没有归因于它的值。

所以,如果我觉得我知道会发生什么,我为什么要问这个问题,你可能会问。这是因为我的一个课程使用了在线代码测试器,并且我的代码在那里出现了段错误,所以,我对此不太熟悉,不确定是不是我的错。

代码按照我发布的方式运行,你可以编译运行,它在文本文件中搜索一个单词;示例:./my_grep "word" "file"

谢谢。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>

#define LINE 1000

static char* word=NULL;
int hasMultiWords=0, iflag=0, vflag=0, lflag=0, cflag=0;

void lowCase(char* s){
    //Nesta funcao recebe um apontador para o inicio de uma string, assim funciona com arrays in *char;
    for(int j=0; j<strlen(s); j++){
        *(s+j) = tolower(*(s+j));
    }

}

void readFile(FILE* in, FILE* out, int argc, char *file_name){

    char line[LINE];
    memset(line, 0, sizeof(char)*1000);
    int n_linhas=0;

    while( fgets(line, LINE, in) ){
        n_linhas++;
        if( cflag==1 && strstr(line, word) !=NULL ){
            printf("%d\n", n_linhas);
            continue;
        }
        if(iflag == 1){
            lowCase(word);
            char *ptr;
            ptr = &line[0];
            lowCase(ptr);
        }
        if( strstr(line, word) != NULL && vflag == 0){
            if(lflag == 1){
                fprintf(stdout, "%s", file_name); 
                break;
            }
            fprintf(stdout, "%s", line);
        }
        if( strstr(line, word) != NULL && vflag == 1 ){
            if(lflag == 1){
                fprintf(stdout, "%s", file_name); 
                break;
            }
            fprintf(stdout, "%s", line);
        }
    }
    
}

int main(int argc, char* argv[]){
    
    FILE* read;
    char* file_name;
    int opt, weirdArgs=0;


    while( (opt=getopt(argc, argv, "ivlc")) != -1){
        switch(opt){
            case 'i':
                iflag=1;
                break;
            case'v':
                vflag=1;
                break;
            case 'l':
                lflag=1;
                break;
            case 'c':
                cflag=1;
                break;
            default: 
                break;
        }
    }

    if(optind > 0){
        word = malloc(sizeof(char)*strlen(argv[optind]));
        word = argv[optind];
    }

    optind++;

    for(; optind<argc; optind++){
        
        weirdArgs++;
        
        file_name = realloc(file_name, sizeof(char)*strlen(argv[optind]));
        file_name = argv[optind];

        if( strcmp(file_name, "-") == 0){
            readFile(stdin, stdout, argc, "stdin");
        }else{
            if( access(file_name, F_OK) != 0 ){
                fprintf(stderr, "%s : No such file.\n", file_name);
                continue;
            }   
            read = fopen(file_name, "r");
            readFile(read, stdout, argc, file_name);
            fclose(read);
        }
        free(file_name);
    }

    if(weirdArgs == 0) readFile(stdin, stdout, argc, "stdin");

    return 0;
}

编辑:所以,它是固定的,我添加了一个 if 语句来检查是否有参数,如果没有,则使程序打印在 stderr 中,因此它不会发现未分配的 optind。谢谢!

if(argc == 1){ 
        fprintf(stderr, "No arguments found.\n"); 
        exit(2);
    }

【问题讨论】:

  • word = argv[optind]; 覆盖 word 并丢失您刚刚从 malloc 获得的内存。
  • 在那之前我被卡住了。我对文档的阅读是 getopt() 返回一个 tuple 。 . .不是整数。据我所知,这也不应该在控制台上工作。我错过了什么?
  • 如果你不传递任何参数,或者你只传递参数开关,你的程序将有未定义的行为,因为行if (optind &gt; 0)确实not认为optind也可以等于或大于argc。所以argv[optind] 是未定义的。如前所述,malloc/realloc 调用只是泄漏内存。即使你使用strcpy(你应该这样做),你也没有分配足够的字节来包含字符串终止符,所以你又会遇到问题。
  • @FrankMerrow:getopt 返回单个字符,在 C 中是一个 int。返回值要么是被识别的单字符选项,要么是一些指示错误的特殊字符,或者 -1 指示已到达参数列表的末尾。 C 没有元组。
  • 另外,malloc(sizeof(char)*strlen(argv[optind])); 不会为终止的空字节分配空间。

标签: c pointers debugging segmentation-fault argv


【解决方案1】:

我用我在最后一次编辑中所说的话解决了这个问题:。 因为我什至不希望程序在没有参数的情况下运行,所以我在它到达可能发生错误的点之前停止它。所以,如果argc等于'1',意味着唯一的参数是程序路径本身,它将exit()它,从而防止分段错误。

我应该在发帖之前考虑一下这个问题,谢谢你的反馈,我确实用它来让它更干净。

【讨论】:

    猜你喜欢
    • 2021-12-20
    • 2014-12-27
    • 1970-01-01
    • 2014-11-01
    • 1970-01-01
    • 2013-04-25
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多