我有这段代码:
char *buffer = calloc(400, sizeof(char));
// buffer gets assigned a string through fgets
if (!regexec(&line_regex, buffer, 400, regmatch_t_var, 0))
// whatever
当条件为false时,字符串buffer
保持不变(根据gdb)
但是当条件为真时,字符串buffer
就会损坏(gdb说<错误:无法访问地址 0xfffffffffffffffff >的内存。)
这真的很奇怪,因为我记得,地址 0xfffffffffffffffff 是内存最低部分的地址,而堆(calloc
)初始化内存最高部分的字节。
有人能解释一下这里发生了什么吗?
这是一个帮助澄清的例子。
首先,创建一个名为 h 的文件,如下所示:ps aux > h
其次,编译:
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
int main(void)
{
FILE *out = fopen("h", "r");
regex_t line_regex;
regcomp(&line_regex, "(\\w|\\+)+\\s+([0-9]+).+ [0-9]+:[0-9]+ (.+)$", REG_EXTENDED);
char *buf = calloc(400, sizeof(char));
regmatch_t pmatch[5];
/* SegFault when the loop continues after passing the condition */
while (fgets(buf, 400, out) != NULL)
if (!regexec(&line_regex, buf, 400, pmatch, 0))
;
fclose(out);
free(buf);
return 0;
}
...与gcc -g
。
第三,用gdb检查代码,你会看到问题所在。
答案 0 :(得分:1)
该错误与您调用regexec
的方式有关。
if (!regexec(&line_regex, buf, 400, pmatch, 0))
^^^ this is wrong
regexec
不要求您告诉它要搜索的字符串的长度;它使用NUL终止。第三个参数应该是pmatch
数组中的条目数。如果我将该参数更改为5,与pmatch
的声明一致,则程序成功执行
您可能想知道为什么必须正确设置此值,因为您的实际正则表达式中只有三组捕获括号。事情是,regexec
被指定为所有不匹配的捕获组的pmatch
条目设置为{ -1, -1 }
...显然,这个实现通过填充整个pmatch
数组来实现,按其第三个参数确定大小,提前{ -1, -1 }
。因此,它写入已声明的数组的末尾并且使用buf
指针。
答案 1 :(得分:-1)
上面的代码是正确的;错误可能在其他地方。
你应该做的第一件事是记下calloc()
的结果,并在条件为真时转储内存。我的猜测是字符串本身仍然很好,但指针 buffer
被覆盖。
请记住:buffer
是堆栈上地址的名称(在函数的本地堆栈框架中的某个位置)。如果你在其他一些局部变量中有缓冲区溢出,那么本地堆栈帧可能会被破坏,你会看到类似突然指向奇数内存位置的指针。