在使用C语言中的regexec/strtok_r时出现了段错误

6

我在确定我为什么会收到分段错误方面遇到了问题。

我正在编写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);
}

我可能犯了一个愚蠢的错误,但如果您能帮助找出segfault原因,我将不胜感激!

编辑:regfree移动到更合适的位置。然而,segfault仍然发生。我相当确定它与正则表达式的读取方式或在regexec中的比较方式有关。虽然一无所知。


调试器怎么样? - Dan Mašek
编译程序以进行调试,并在调试器下运行程序。调试器将准确告诉您发生了什么。 - wallyk
很抱歉要说您在使用调试器时出了问题。当GDB停止时,bt将列出导致停止的堆栈跟踪,而print nameOfVariable将打印出nameOfVariable的当前状态。当因段错误而停止时,您可以查看导致此错误的原因,并开始阅读变量以查看哪些可能会导致问题。 - user4581301
1
你的正则表达式不起作用,因为你没有从fgets中去掉换行符。 - Joshua
@Joshua 在添加 len = strlen(para); para[len-1] = '\0'; 后,正则表达式仍然无法正常工作。 - higz555
显示剩余2条评论
3个回答

3

不要这样:

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

请写下以下内容:

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

在第一种情况下,para 是一个指针,它指向内存中的某个位置,并将用户输入的字符串写入到这个位置。很可能,para 指向一个无效的地址,从而立即导致程序崩溃。

修复了分段错误 - 谢谢!现在我的正则表达式没有被正确分析。回到起点重新设计。 - higz555

2

您在循环内部调用了regfree函数。在循环的第二次迭代中,您尝试对已释放的内存调用regexec函数, 这将导致未定义的行为。


0

您正在错误地使用 strtok_r()

要使用 strtok_r() 解析字符串,第一次调用时,第一个参数是指向要解析的字符串的指针。后续对 strtok_r() 的调用以解析相同的字符串应将 NULL 作为第一个参数传递。你现在的做法:

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

毫无意义。


我的理解是,strtok_r 中的指针在找到分隔符后指向拆分字符串,因此它可以递归地切割字符串。这对我很有效。 - higz555
1
我明白。我经常这样使用 strtok_r。 - Joshua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接