调试无意中使用内存“属于”父函数

时间:2012-11-28 19:37:06

标签: c++ debugging memory valgrind

假设我有一个从给定软件工具调用的函数foo(在C / C ++中)。

只允许函数foo写入由foofoo调用的函数之一分配的内存,而不是写入由foo调用的内存。在调用foo之前执行的函数。

我强烈怀疑在某个地方{{1}}写入内存是不允许的。

有没有办法系统地调试这种行为?对valgrind来说可能是一些奇特的旗帜?

4 个答案:

答案 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或类似的东西,它不会做它不应该做的事情。另一种选择是使用一个调试库来跟踪/监视内存使用情况,并在内存错误发生时标记它们。