Обнаружение ошибок сегментации при запуске очень старого кода C - PullRequest
0 голосов
/ 20 апреля 2019

как часть курса по искусственному интеллекту, я исследую игру Решая бот (Rolling Stone) я нашел здесь . Этот код был написан в 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;
        /* test if goal is in the pattern, if yes, no deadlock  or
         * test the mirror pattern to see if that finds a deadlock */

        /* check for pattern overflow first */
        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);

Но массив пусто, поэтому мы получаем ошибку сегментации. Вот код в вопрос

Я перенес код на GitHub. Вы можете проверить это здесь

Примечание. Я также пытался запустить этот код в Ubuntu 16.04.06 X86 и Visual Studio 2019, но безуспешно.

1 Ответ

2 голосов
/ 20 апреля 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 является typedef для int[3]. Быстрый взгляд на DL.1 показывает, что это 32-разрядные целые числа с прямым порядком байтов. Если вы используете это на x86, то ваш int имеет 32-битный порядок байтов. Таким образом, вам нужно будет поменять байты этих данных после прочтения (например, зациклив их на ntohl().)

Если это указывает на переносимость остальной части кода, то я думаю, что перенос его на ваш текущий компьютер может быть существенным проектом.

...