在运行非常旧的C代码时遇到分段错误

作为人工智能课程的一部分,我正在研究一个游戏解决机器人(滚动石头),我是在这里找到的。这个代码是1999年写的(可能是在HP UNIX工作站上)。我无法在我的平台(Ubuntu Linux 18.10 x64)上运行它。我遇到了分段错误(SIGSEGV, SIGBUS等)

该代码使用了自定义编写的数据结构,比如通过指针运算和引用调用使用的位字符串。例如,在一个实例中,我们通过index = t->Array[index][square];获取某种类型块的索引

我们检查玩家移动到哪些可能的状态中,是否有空块或墙壁。

do {        p = pos + xofs*t->Sup[i].x_ofs + yofs*t->Sup[i].y_ofs;        /* 测试目标是否在模式中,如果是,则没有死锁,或者         * 测试镜像模式,看看是否发现死锁 */        /* 首先检查模式溢出 */        if (p<0 || p>XSIZE*YSIZE)             square = WallSquare;        else {            if (maze->Phys[p].goal >= 0) {                goto TEST_MIRROR;            }            if (IsBitSetBS(maze->out,p)) square = WallSquare;            else if (maze->PHYSstone[p]>=0) square = StoneSquare;            else square = BlancSquare;        }        index = t->Array[index][square];        i++;       } while (index>0);

但是,Array是空的,所以我们得到了分段错误。 这是相关代码

我已经将代码移植到GitHub。你可以在这里查看 这里

注意:我还尝试在Ubuntu 16.04.06 X86和Visual Studio 2019中运行这个代码,但没有成功。


回答:

在我的测试中,第一次通过这段代码时(当index=0),我们发现t->Array[0]包含一些巨大的数字。因此,index被发送到一个巨大的值,在下一次循环中,它超出了t->Array的大小,导致崩溃。

t->Array的内容最初是从文件DL.1在函数LoadTree中加载的:

        t->Next[0] = fread(t->Array,sizeof(DLENTRY),                t->CurrentLength,fp);

不幸的是,作者选择以他们机器的原生二进制格式存储这些数据,这可能与你当前的机器不兼容。

现在DLENTRYint[3]的typedef。快速浏览DL.1表明,它似乎是大端32位整数。如果你在x86上运行,那么你的int是32位小端。因此,你需要在读取后交换这些数据的字节顺序(例如,通过使用ntohl()循环处理)。

如果这表明了代码其余部分的可移植性,那么我认为将它移植到你当前的机器上可能是一个相当大的项目。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注