作为人工智能课程的一部分,我正在研究一个游戏解决机器人(滚动石头),我是在这里找到的。这个代码是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);
不幸的是,作者选择以他们机器的原生二进制格式存储这些数据,这可能与你当前的机器不兼容。
现在DLENTRY
是int[3]
的typedef。快速浏览DL.1
表明,它似乎是大端32位整数。如果你在x86上运行,那么你的int
是32位小端。因此,你需要在读取后交换这些数据的字节顺序(例如,通过使用ntohl()
循环处理)。
如果这表明了代码其余部分的可移植性,那么我认为将它移植到你当前的机器上可能是一个相当大的项目。