我是一名C初学者,现在已经解决了这个问题,我和我的同事们无法找到解决方案。
问题的第1部分: 我使用大多数Linux发行版中包含的标准C正则表达式lib(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: 我通常想释放我分配的内存。因为我分配了theRegex,所以我希望在循环结束时用
释放它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!
答案 0 :(得分: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
};