1

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

函数foo只允许写入被foo调用的函数或被调用的函数之一分配的foo内存,而不能写入调用前已经执行的函数分配的内存foo

我强烈怀疑在某些地方foo不允许写入内存。

有没有办法系统地调试这种行为?也许一些花哨的旗帜给 valgrind?

4

4 回答 4

1

Valgrind 手册有一些你的程序可以调用的 Valgrind 函数。

看起来VALGRIND_MAKE_MEM_NOACCESS可能是你想要的。

于 2012-11-29T22:11:42.880 回答
0

您可以使用自定义分配器(想到Boost Pool)来确保您要“保护”的所有内存都是连续分配的。

接下来,在该内存区域中的任何数据发生更改时设置硬件断点。

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

于 2012-12-03T22:34:47.367 回答
0

我会编写一个 GDB 脚本,在您的函数上设置断点,然后在您怀疑正在更改的内存上设置硬件监视,然后继续。

如果函数foo正在修改该内存,则硬件手表将在执行该操作的指令上触发。

GDB 脚本可能如下所示:

break foo
commands
up
watch array
down
continue
end

我没有对此进行测试,它可能需要调整,尤其是手表表达式。您可能仅限于查看一个数组元素。我相信硬件观察点实际上只能观察一个整数大小的块:32 位上的 4 个字节或 64 位上的 8 个字节。

于 2012-11-28T19:56:41.237 回答