【问题标题】:Stopping strstr before it runs into sigsegv在 strstr 遇到 sigsegv 之前停止它
【发布时间】:2019-12-20 20:57:03
【问题描述】:

我有一个很大的 .xml 文件,需要从中提取特定的部分。 我需要拉出的东西被两边的子字符串封装。 我需要将输出写入文件。

我正在寻找起始子并从那里寻找结束子,然后将其复制并通过 fprintf 输出。 我将开始指针设置为最后一个结束指针的位置,它会继续搜索,直到遇到 sigsegv。

我不知道如何在循环进入 sigsegv 之前在我正在搜索的子字符串的最后一次出现处停止循环。

我遇到的一个有趣的问题是,如果我输出到 stdout,它会打印出我想要提取的所有内容,然后崩溃。 如果我想将它写入一个文件,它不会写入相同的内容,而是会在它完成之前发生故障,并且在此过程中丢失最后 37 行输出。

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

int main(void) {

    FILE *fp;
    fp = fopen("C:/Users/entin/Desktop/IHP/Auswerte_Marko/TEMP/20190605204730250_S210D_PQ41701_TM2_TV2_MARK21Single_21Single.ega_rslt", "r");

    FILE *fw;
    fw = fopen("C:/Users/entin/Desktop/IHP/Auswerte_Marko/TEMP/t1.xml", "w");

    int f_length;
    fseek(fp, 0, SEEK_END);
    f_length = ftell(fp);
    char file[f_length + 1];
    rewind(fp);
    fread(file, f_length, 1, fp);
    file[f_length] = 0; 



    const char *SPattern = "<MeasData "; // start of substring
    const char *EPattern = "</MeasData>"; // end of substring
    char *start, *end;
    char *target = NULL;

    if (start = strstr(file, SPattern)) { // search for start substring
        start += strlen(SPattern);
        if (end = strstr(start, EPattern)) { // search for end substring
            target = (char *) malloc(end - start + 1);
            memcpy(target, start, end - start); // copying content between start and end pointers
            target[end - start] = '\0';

            start = end; // setting new start to old end
        }
    }

    if (target) fprintf(stdout, "%s%s%s\n", SPattern, target, EPattern); // assembling everything back together

    free(target);


    //while (end <= EOF) { // repeating till end of file is reached
    while (end != NULL && *end != 0){ //EDIT from comments
        char *target = NULL;
        if (start = strstr(start, SPattern)) { // startig search from last end pointer
            start += strlen(SPattern);
            if (end = strstr(start, EPattern)) {
                target = (char *) malloc(end - start + 1);
                memcpy(target, start, end - start);
                target[end - start] = '\0';

                start = end;
            }
        }

        if (target) fprintf(stdout, "%s%s%s\n", SPattern, target, EPattern);

        free(target);
    }

    fclose(fp);
    fclose(fw);
    getchar();
    return 0;
}

这里是文件:

Input File

Output to stdout that I want in a file

Output that I get when I write to a file

(仅输出的最后几行)

【问题讨论】:

  • while (end &lt;= EOF) 这是不正确的。 EOF 是一个常数值,表示文件结束。它不适合任何东西,但检查是否相等。 “小于或等于”没有任何意义。 end 也是一个指针,而 EOF 是一个整数值。您是否打算使用while(end != NULL &amp;&amp; *end != 0)
  • while (end &lt;= EOF):这没有任何意义: 1:您将 指针 endEOF 进行比较,后者不是指针; 2:在while循环中你没有做任何文件操作,所以测试EOF无论如何都没有意义。
  • 如果start 没有被设置为非NULL 值,那么end 将不会被设置。 end 在测试之前没有被初始化,所以你有未定义的行为
  • char file[f_length + 1]; 是危险的,如果 f_length 超出堆栈帧的容量。哦,不要忽略fread()的返回值。
  • 这可能是因为stdout 是行缓冲的,每个printf 都会立即显示在终端上。 OTOH,文件可以有更大的缓冲区,当您的程序停止崩溃和刻录时,缓冲区不会被刷新。

标签: c eof segmentation-fault file-writing strstr


【解决方案1】:

您不应该检查end,而是检查start

while (end != NULL && *end != 0){ //EDIT from comments
    char *target = NULL;
    if (start = strstr(start, SPattern)) { // startig search from last end pointer
        start += strlen(SPattern);
        if (end = strstr(start, EPattern)) {
            target = (char *) malloc(end - start + 1);
            memcpy(target, start, end - start);
            target[end - start] = '\0';

            start = end;
        }
    }

    if (target) fprintf(stdout, "%s%s%s\n", SPattern, target, EPattern);

    free(target);
}

如果您找到最后一个元素并搜索下一个元素,start 将是NULL,您将不会进入if 块。 在这种情况下,您无需更改 end 并再次调用 strstr,但现在使用 start == NULL

据我所知,strstr 不需要验证指针是否有效。

在你的循环中,end 只会变成NULL,如果你找到开始模式但没有结束模式。对于有效的 XML 文件,这不太可能发生。

【讨论】:

  • 请注意,end 在首次使用之前是未初始化的。 OP 的代码还有很多错误,没有一个简单的修复方法。
猜你喜欢
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 2021-11-29
  • 2021-03-13
  • 1970-01-01
  • 2018-03-18
  • 2021-10-19
  • 1970-01-01
相关资源
最近更新 更多