【问题标题】:Segmentation fault when using regexec/strtok_r in C在 C 中使用 regexec/strtok_r 时出现分段错误
【发布时间】:2016-04-22 22:24:20
【问题描述】:

我无法确定收到分段错误的位置和原因。

我正在编写一个 C 代码,提示用户输入一个正则表达式并编译它,然后输入一个包含多个句子的字符串:

int main(void){

  char RegExp[50];
  regex_t CompiledRegExp;
  char *para;
  char delim[] = ".!?,";
  char *sentence;
  char *ptr1;

  printf("Enter regular expression: ");
  fgets(RegExp, 50, stdin);

if (regcomp(&CompiledRegExp,RegExp,REG_EXTENDED|REG_NOSUB) != 0) {                        

    printf("ERROR: Something wrong in the regular expression\n");                         

    exit(EXIT_FAILURE);                                                                   

  }

  printf("\nEnter string: ");

strtok_r 用于使用以下任一分隔符分割字符串 .,?!然后将生成的标记(句子)用作 regexec 函数中的字符串参数,该函数会搜索它以查看之前编译的正则表达式是否包含在标记中:

if( fgets(para, 1000, stdin)){

    char *ptr = para;
    sentence = strtok_r(ptr, delim, &ptr1);

    while(sentence != NULL){

      printf("\n%s", sentence);

      if (regexec(&CompiledRegExp,sentence,(size_t)0,NULL,0) == 0) {
        printf("\nYes");
      } else {
        printf("\nNo");
      }
      ptr = ptr1;
      sentence = strtok_r(ptr, delim, &ptr1);

    }
  }
regfree(&CompiledRegExp);
}

这可能是我正在犯的一个愚蠢的错误,但在找到 segfaul 的原因方面的任何帮助将不胜感激!

编辑: regfree 移至更合适的位置。但是,段错误仍然发生。我很确定这与正则表达式的读取方式或regexec 中的比较方式有关。然而,毫无头绪。

【问题讨论】:

  • 调试器呢?
  • 编译调试程序,在调试器下运行程序。调试器会告诉你到底发生了什么。
  • gdb 调试器没有给我任何细节 - 只是声称发现了一个段错误
  • 怕是说你用的调试器不对。当 GDB 停止时,bt 将列出导致停止的堆栈跟踪,print nameOfVariable 将打印出 nameOfVariable 的当前状态。当因段错误而停止时,您可以查看导致它的原因并开始读取变量以查看可能导致错误的变量。
  • 您的正则表达式不起作用,因为您没有从 fgets 中删除换行符。

标签: c regex segmentation-fault strtok


【解决方案1】:

而不是这个:

char *para;
fgets(para, 1000, stdin);

这样写:

char para[1000];
fgets(para, 1000, stdin);

在第一个变体中,para 是一个指针,它指向内存中的somewhere,用户输入的字符串被写入到这个somewhere。最有可能的是,para 指向某个无效地址,从而立即使您的程序崩溃。

【讨论】:

  • 修复了分段错误 - 谢谢!现在我的正则表达式没有被正确分析。回到绘图板。
【解决方案2】:

您在循环内调用了 regfree。第二次在循环中调用 regexec 以释放未定义行为的内存。

【讨论】:

    【解决方案3】:

    您错误地使用了strtok_r()

    要解析带有strtok_r() 的字符串,在第一次调用中,第一个参数是指向要解析的字符串的指针。随后调用strtok_r() 来解析相同的字符串应该将NULL 作为第一个参数传递。你在做什么:

    ptr = ptr1;  
    sentence = strtok_r(ptr, delim, &ptr1); 
    

    没有意义。

    【讨论】:

    • 我的理解是 strtok_r 中的指针在找到分隔符后指向拆分字符串,因此它可以递归地切穿字符串。它对我有用。
    • 对我来说很有意义。我经常使用 strtok_r。
    猜你喜欢
    • 2011-01-14
    • 2021-01-01
    • 1970-01-01
    • 2018-07-20
    • 1970-01-01
    • 2021-06-13
    • 2013-04-03
    • 2016-09-15
    • 2020-11-21
    相关资源
    最近更新 更多