1

我是一个 C 初学者,现在已经在这个问题上工作了几个星期,我和我的同事都想不出解决方案。

问题的第 1 部分: 我使用大多数 Linux 发行版中包含的标准 C 正则表达式库 (regex.h)。在网上的许多例子中,我使用了一个看起来像这样的匹配函数

int match(const char *string, char *pattern) {
int    status;
regex_t    re;

if (regcomp(&re, pattern, REG_EXTENDED) != 0) {
    char    buffer[100];
    regerror(status, &re, buffer, 100);
    printf("regcomp() failed with '%s'\n", buffer);
    return(0);      /* Report error. */
}
status = regexec(&re, string, (size_t) 0, NULL, 0);
regfree(&re);
if (status != 0) {
    char    buffer[100];
    regerror(status, &re, buffer, 100);
    printf("regcomp() failed with '%s'\n", buffer);
    return(0);      /* Report error. */
}
printf("match: %s<\n",string);
return(1); 
}

然后,我有一个带有一些正则表达式的主函数,要针对输入进行检查(在这种情况下,我通过值 [1] 进行了模拟)。在这种情况下,它应该只匹配第二个值条目,其余的应该返回 0。

int main() {
 int i = 0;
 char* values[16] = {"ADCICT.A100311.ANTRAG","ADCICT.A100311.ANTRAG.NR","ADDB2P.K004111.PLANxUEB","ADDB2Q.K004111.PLANxUEB","ADDB2P.K004111.PRODxUEB**",
 "ADDB2Q.K004111.PRODxUEB**","ADDB2P.K004111.SQLCODE","ADDB2Q.K004111.SQLCODE","ADDB2P.K004111.VORP#UEB","ADDB2Q.K004111.VORP#UEB",
 "ADEDVT.A347709.DDIO.*.PGM%COB**","AD000T.K001800.CICS.**","A9VIST.K001804.INFOS","ABC4","ABC5"}; 

 for ( i = 0; values[i] != NULL; i++ ) {
    char *theRegex = (char *) malloc(100);
    memset(theRegex, 0x00, 100);
    theRegex = values[i];
    printf("regexV=%x<", theRegex);
    transformRegex(&theRegex);
    printf("regexN=%s< ", theRegex);
    int reti = match(values[1], theRegex);
    printf("reti=%i\n", reti);
    fflush(stdout);
    //free(theRegex);
 }
}

transformRegex 采用 char* 并在开头添加 ^ 并在末尾添加 $:

int transformRegex(char **regexS){
    char tmpStr[strlen(*regexS)+3];
    memset(tmpStr, 0x00, strlen(*regexS)+3);
    memcpy(tmpStr, "^", 1);
    memcpy(&tmpStr[1], *regexS, strlen(*regexS));
    strcat(tmpStr,  "$");
    *regexS = tmpStr;
    return 0;
}

实际上,transformRegex 函数应该做更多的事情,但是由于我无法找到解决这个问题的方法,我不得不尽可能多地删除代码,现在我真的非常非常筋疲力尽,因为我无法解决它.

如果我运行这个程序(使用 gdb),我得到的是:

regexV=4010dc<regexN=^ADCICT.A100311.ANTRAG$< match: ADCICT.A100311.ANTRAG.NR<
reti=1
regexV=4010f2<regexN=^ADCICT.A100311.ANTRAG.NR$< match: ADCICT.A100311.ANTRAG.NR<
reti=1
regexV=40110b<regexN=^ADDB2P.K004111.PLANxUEB$< regcomp() failed with 'No match'
  [...]
reti=0
regexV=401207<regexN=^A9VIST.K001804.INFOS$< regcomp() failed with 'No match'
reti=0
regexV=40121c<regexN=^ABC4$< match: ADCICT.A100311.ANTRAG.NR<
reti=1
regexV=401221<regexN=^ABC5$< match: ADCICT.A100311.ANTRAG.NR<
reti=1

最后两件事怎么可能匹配?更别提第一个了……

问题2: 我以前经常注意到这个问题,但它似乎自行消失了。如果我只是拿出这条线

printf("regexV=%x<", theRegex);

我的第一行输出是

regexN= Üÿÿ< regcomp() failed with 'No match'
reti=0

以上帝的名义这是什么?printf 语句如何影响我的代码?

问题3: 我通常想释放我分配的内存。因为我分配了正则表达式,所以我想在循环结束时释放它

free(theRegex)

但是看看如果我这样做会发生什么:

regexV=4010ec<regexN=^ADCICT.A100311.ANTRAG$< match: ADCICT.A100311.ANTRAG.NR<
reti=1
*** glibc detected *** /home/itgsandbox/KK/a.out: double free or corruption (out): 0x00007fffffffdb70 ***
 [...]
Program received signal SIGABRT, Aborted.
0x00007ffff7ab2945 in raise () from /lib64/libc.so.6

我真的束手无策(这并不意味着什么,因为我刚从 C 开始),但这些问题似乎可以由非常微妙的人来解决。请帮助我,我相信你,Stackoverflow!

4

1 回答 1

0

发布的代码存在一些问题(OP 提到的问题可能或多或少是由于这些问题,因此请修复问题并查看代码的执行情况):

这里

int transformRegex(char **regexS){
  char tmpStr[strlen(*regexS)+3];
  ....
  *regexS = tmpStr;
  return 0; 
}

该代码返回对仅在内部分配的内存的引用transformRegex。它在函数返回时变得无效。

稍后访问内存会导致未定义的行为。


这些线

  char *theRegex = (char *) malloc(100);
  memset(theRegex, 0x00, 100);

是无意义的和泄漏的内存,如下一行

  theRegex = values[i];

的返回值malloc()被覆盖,因此丢失。


调用free()失败,因为传入的值是指无效内存(见上文)。


更新:

这个数组

char* values[16] = {
  "ADCICT.A100311.ANTRAG","ADCICT.A100311.ANTRAG.NR","ADDB2P.K004111.PLANxUEB",
  "ADDB2Q.K004111.PLANxUEB","ADDB2P.K004111.PRODxUEB**","ADDB2Q.K004111.PRODxUEB**",
  "ADDB2P.K004111.SQLCODE","ADDB2Q.K004111.SQLCODE","ADDB2P.K004111.VORP#UEB",
  "ADDB2Q.K004111.VORP#UEB","ADEDVT.A347709.DDIO.*.PGM%COB**","AD000T.K001800.CICS.**",
  "A9VIST.K001804.INFOS","ABC4","ABC5"
}; 

没有任何值为 的元素NULL

所以这一行的条件

for ( i = 0; values[i] != NULL; i++ ) {

永远不会触发。如果确实如此,则数组订阅远远落后于定义的内容。越界访问数组元素也会引发未定义行为。

要解决此问题,您可能希望删除数组大小声明并向数组添加“Stopper”元素,如下所示:

char* values[] = {
  "ADCICT.A100311.ANTRAG","ADCICT.A100311.ANTRAG.NR","ADDB2P.K004111.PLANxUEB",
  "ADDB2Q.K004111.PLANxUEB","ADDB2P.K004111.PRODxUEB**","ADDB2Q.K004111.PRODxUEB**",
  "ADDB2P.K004111.SQLCODE","ADDB2Q.K004111.SQLCODE","ADDB2P.K004111.VORP#UEB",
  "ADDB2Q.K004111.VORP#UEB","ADEDVT.A347709.DDIO.*.PGM%COB**","AD000T.K001800.CICS.**",
  "A9VIST.K001804.INFOS","ABC4","ABC5",
  NULL
}; 
于 2013-08-02T09:26:36.797 回答