假设我有一个从给定软件工具调用的函数foo
(在C / C ++中)。
只允许函数foo
写入由foo
或foo
调用的函数之一分配的内存,而不是写入由foo
调用的内存。在调用foo
之前执行的函数。
我强烈怀疑在某个地方{{1}}写入内存是不允许的。
有没有办法系统地调试这种行为?对valgrind来说可能是一些奇特的旗帜?
答案 0 :(得分:1)
Valgrind manual有一些程序可以调用的Valgrind函数。
看起来VALGRIND_MAKE_MEM_NOACCESS
可能就是你想要的。
答案 1 :(得分:0)
您可以使用自定义分配器(Boost Pool)来确保您想要“保护”的所有内存都是连续分配的。
接下来,当该内存区域中的任何数据发生更改时,设置硬件断点。
答案 2 :(得分:0)
我会写一个GDB脚本,在你的函数上设置断点,然后在你怀疑被改变的内存上设置硬件监视,然后继续。
如果函数foo
正在修改该内存,硬件监视将在该指令上执行该操作。
GDB脚本可能如下所示:
break foo
commands
up
watch array
down
continue
end
我没有测试它,它可能需要调整,特别是手表表达。您可能只能观看一个数组元素。我相信硬件观察点实际上只能看一个整数块:32位4字节或64位8字节。
答案 3 :(得分:0)
foo()可以写入其范围之外的内存的唯一方法是,如果该内存是全局的,即外部变量,或者如果foo()有一个或多个参数,这些参数本来是只读的,但不知何故它们被修改了
要验证调用参数是否被修改,您可以创建一个结构来保存参数,并在返回比较原始参数和保存的参数之前。
struct foo_args {
int a;
char *b;
};
void
foo(int a, char *b)
{
struct foo_args args;
args.a = a
args.b = strdup(b);
/* The rest of the foo() code. */
if (args.a != a || strcmp(args.b, b) != 0) {
printf("error - args got modified\n");
}
free(args.b);
}
如果上面没有捕获它,那么可能的情况是全局,堆栈或堆内存都被破坏了。
让valgrind运行该工具可能不实用,在这种情况下,您需要为foo()创建一个“包装器”,并确保使用valgrind或类似的东西,它不会做它不应该做的事情。另一种选择是使用一个调试库来跟踪/监视内存使用情况,并在内存错误发生时标记它们。