gpt4 book ai didi

c - 如何解决一个奇怪的变化值?

转载 作者:行者123 更新时间:2023-12-04 05:05:20 24 4
gpt4 key购买 nike

我正在为一种小型计算机语言制作虚拟机。这个虚拟机是使用 GNU 实用程序 Flex 用 C 语言开发的。因此,项目编译使用 GNU GCC,然后使用 Flex。

在这个虚拟机中,我有一个 GC 停止和复制。在我更改之前,GC 的工作内存无法扩大 - 例如,如果第一次翻转没有优化用于进行新分配的空间,则从 512 字节增加到 1024 字节。

这种改变似乎奏效了。事实上,我不知道自从这些更改后它是否真的有效,但现在我有一个错误。它刚刚出现在第一次翻转中。确实,说到复制数据,我有一个不变的变量 .但是这个变量很重要,因为它指向我想要复制的项目。在停止和复制中,此变量用于更改插槽(此处为 SLOT_FORWARD )以通知数据在内存中的新位置(以防我们仍要复制)。

所以我有一个循环复制前一个容器的每个框,其在内存中的位置由变量 old 指定。 .我有一个从 addr 装满的新容器位置。 但是旧值在迭代过程中发生了变化! 复制后,我想将插槽向前更改以放置新容器的地址。但是随着旧的改变,你可以想象我在错误的地方记录了这个值。

因此,我花了很长时间调试这种情况很少发生的情况(在 3 到 4 个容器进行 2 次翻转后有时会发生这种情况)。我使用 GDB 来了解在我的调试功能之一中更改的值(同时她也通过添加调试功能进行了修改)。然后我更改了编译器(clang 到 gcc)以重新启动 GDB 并看到它是一个大括号字符(仍在调试函数中)改变了值......最后,我把所有函数的所有参数const当有可能时,现在我被告知文件 iofwrite.c 中的值已更改第 37 行。因此,这是来自另一个世界的错误。

有问题的代码在这里是错误的:

static t_case
copy(t_dono *dono, const t_case old)
{
t_case addr;
t_case size;
t_case temp;
int i;

temp = old;

if (mem[old + SLOT_FORWARD] >= ns
&& mem[old + SLOT_FORWARD] <= ts)
return (mem[old + SLOT_FORWARD]);
else
{
addr = mp;
size = mem[old + SLOT_SIZE];
i = 0;

fprintf(stderr, "change:\t");
dump(stderr, mem, old);

assert(old == temp);

while (i < size)
{
fprintf(stderr, "!!!COPY:\t");
dump(stderr, mem, old);
assert(old == temp);
mem[addr + i] = mem[old + i]; /* BUG IS HERE */
i = i + 1;
}

mem[old + SLOT_FORWARD] = addr;
fprintf(stderr, "change:\t");
dump(stderr, mem, old);
assert(old == temp);
mp = mp + size;

return (addr);
}
}

正如你所看到的,我做了很多调试来定位错误,我得到了这个日志文件:
ref:            [ 0005 0001 0003 0004 0035 ]
copy: [ 0007 0001 0003 0004 0075 0001 00f9 ]
change: [ 0007 0001 0003 0004 0075 0001 00f9 ]
!!!COPY: [ 0007 0001 0003 0004 0075 0001 00f9 ]
!!!COPY: [ 0007 0001 0003 0004 0075 0001 00f9 ]
!!!COPY: [ 0007 0001 0003 0004 0075 0001 00f9 ]
!!!COPY: [ 0003 0001 0003 ]
!!!COPY: [ 0003 0004 0003 ]
!!!COPY: [ 0003 0004 0075 ]
!!!COPY: [ 0003 0004 0075 ]
change: [ 0003 0033 0075 ]

我还使用了 Valgrind,它告诉我很多错误,但只有在这个错误之后(这是正常的,因为 GC 现在将访问随机数据)。在此变量更改期间,我绝对没有错误。

我们可以看到,通过函数 copy (l: 662) 的其他容器没有得到这种未定义的行为(请参阅第 10、48、54、66、82、120、126 和 134 行的日志文件)。只是在执行时,一切都会出错,当然,这会导致所有 GC 数据出错。

代码真的很长(大约 1000 行),因为目标是在单个文件 C 中运行 VM。对不起,我不能让代码更清晰。但问题只是神奇地出现了,我无法更进一步,使 future 的语言能够超越 Python(笑话)。

存储库链接为: git.osau.re
更改链接是: ompldr

亲切的问候。

最佳答案

追踪随机内存破坏(这听起来像)非常困难。我的方法是弄清楚编译器何时决定将更改的变量(可能在堆栈中的某个位置)放置,然后为该位置设置一个观察点。这应该会告诉您代码在哪里修改值——您可能会发现它在某个被调用的函数中,该函数正在逐步返回堆栈以单步执行您的变量。然后你需要弄清楚为什么会发生这种情况。

关于c - 如何解决一个奇怪的变化值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15580122/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com