【问题标题】:Segmentation fault with global pointers全局指针的分段错误
【发布时间】:2016-12-07 04:15:38
【问题描述】:

我正在尝试定义一个全局指针变量,然后可以在主函数中真正设置它,如下所示。但是,在此之后,每当我尝试使用 outputName 时,我都会遇到分段错误。我知道这可能与在开始时将指针设置为等于NULL 有关......任何关于我如何拥有一个然后在 main 中设置的全局指针的帮助都会非常有帮助!这是我的代码中出现错误的部分:

    char* outputName = NULL;

    int isNumber(char number[]){
        int i;
        if (number[0] == '-')
            i = 1;
        
        while(number[i] != '\0'){
            if (!isdigit(number[i]))
                return 0;

            i++;
        }

        return 1;
    }

    void catcher(int signo){
        printf("The program is exiting early");
        remove(outputName);
        exit(1);
    }

    int main(int argc, char *argv[]){
        if (argc != 4){
            fprintf(stderr,"Incorrect number of arguments, must supply three.\n");
            exit(1);
        }

        char* inputName = argv[1];
        outputName = argv[2];
        signal(SIGINT, catcher);
        int result = isNumber(argv[3]);
        
        if (result == 0){
            fprintf(stderr, "Invalid maximum line length, please enter an integer\n");
            exit(1);
        }
        
        int maxChars = (atoi(argv[3])) + 1;
        if ((maxChars-1) < 1){
            fprintf(stderr, "Invalid third maximum line length, please enter an integer greater than zero\                                          
    .\n");
            exit(1);
        }

        FILE* inFile = fopen(inputName, "r");
        if (inFile == NULL){
            fprintf(stderr, "Error while opening %s.\n", inputName);
            exit(1);
        }

        FILE* outFile = fopen(outputName, "w");
        if (outFile == NULL){
            fprintf(stderr, "Error while opening %s.\n", outputName);
            exit(1);
        }                                                                                               
        
        char line[maxChars];
        int done = 0;
        while (!done){
            char *readLine = fgets(line, maxChars, inFile);
            if (readLine == NULL){
                if (errno == 0){
                    done = 1;
                } else {
                    fprintf(stderr, "Error when reading line from input file");
                    exit(1);
                }
            }

            int len = strlen(line);
            if (line[len-1] != '\n'){
                line[len] = '\n';
                line[len+1] = '\0';
                char current = ' ';

                while (current != '\n')
                    current = getc(inFile);
            }

            if (!done){
                fputs(line, outFile);
                if (errno != 0){
                    fprintf(stderr, "Error when writing line to output file");
                    exit(1);
                }
            }
        }

        return 0;
    }

【问题讨论】:

  • 所以如果outputName在上面的代码之后是有效的,那么问题就出在别的地方了……
  • 你能提供一个完整的代码块吗?可能是完整的主要功能以及之后您对outputName 所做的事情。
  • 这确实取决于您将其设置为什么。如果将其设置为超出范围的局部变量,则会出现未定义的行为。
  • 我确实编译了你的代码,它就像一个魅力。您确定这段代码在您的计算机上崩溃了吗?
  • 请注意,如果您想合理地确定它们会出现,您应该使用换行符终止printf() 输出;如果您想要更大的确定性,也可以使用fflush(stdout);。然后记下How to avoid using printf() in a signal handler。您可能会侥幸逃脱——这不太可能是您遇到麻烦的原因,但由于在分配给 outputName 后您没有显示任何代码,因此很难知道您在做什么。你说你使用outputName,但唯一显示使用它的地方是在信号处理程序中。你在打断它吗?

标签: c pointers segmentation-fault global errno


【解决方案1】:

可能是在 outputName 设置为非空值之前调用了信号处理程序,您可以尝试在 outputName = argv[2] 之后设置信号处理程序;在 main() 中

【讨论】:

    【解决方案2】:

    仔细阅读signal(7):因为你的catcher 调用printf,这不是一个异步信号安全函数,你的代码有undefined behavior。此外,您的 printf 控制字符串不以 \n 结尾,并且由于 stdout 是行缓冲的,因此不会进行任何输出。首选sigaction(2) 而不是signal,并在分配outputName 之后安装您的信号处理程序。

    信号处理程序中使用的全局变量应声明为volatile。所以在全球范围内声明你的char* volatile outputName;。然后你可能在处理程序中有一个像if (outputName != NULL) remove(outputName); 这样的测试。一种常见的做法是在信号处理程序中设置一些 volatile sig_atomic_t 全局标志,并在其他地方测试该标志。

    而且您的程序很可能没有时间获取任何信号。您可能应该等待一段时间来结束您的 main 函数(例如,从 stdinusleep(3)pause(2)poll(2)...读取)。

    当然,使用所有警告和调试信息 (gcc -Wall -g) 编译您的代码并使用调试器 (gdb);我想调试器watchpoints 应该对找到您的错误非常有用。

    您展示的节目可能不会展示任何 SEGV。所以你的实际错误很可能在其他地方。

    也许使用strace(1) 和/或valgrind 也有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-02
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      • 2013-09-18
      • 2016-02-24
      • 1970-01-01
      相关资源
      最近更新 更多