#debugging #gcc #undefined-behavior #illegal-instruction
#отладка #gcc #неопределенное поведение #незаконная инструкция
Вопрос:
Я работаю над программой, использующей научную библиотеку GNU. Он выдает «незаконную инструкцию (дамп ядра)» после решения нелинейного уравнения пополам. Смотрите ниже. Какова обычная причина такой ошибки «незаконной инструкции» и как я мог отлаживать в таких ситуациях?
...
iter 0: A = 1.0000, lambda = 1.0000, b = 0.0000, cond(J) = 6.0000, |f(x)| = 101.0200
iter 1: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = 92.8216, |f(x)| = -nan
iter 2: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 3: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
iter 4: A = 3.5110, lambda = -12.8820, b = 1.2364, cond(J) = nan, |f(x)| = -nan
Illegal instruction (core dumped)
С gdb
помощью я получил немного дополнительной информации.
Program received signal SIGILL, Illegal instruction.
0x00000000004d1030 in nielsen_reject (nu=<optimized out>, mu=<optimized out>) at nielsen.c:98
98 *nu <<= 1;
(gdb) p nu
$1 = <optimized out>
(gdb) x/i $pc
=> 0x4d1030 <trust_iterate 8912>: ud2
Выше nielsen.c98
выглядит так
...
static int
nielsen_reject(double * mu, long * nu)
{
*mu *= (double) *nu;
/* nu := 2*nu */
*nu <<= 1;
return GSL_SUCCESS;
}
Процессор — x86_64 в соответствии с uname -m
. ОС — Ubuntu 16.04 VirtualMachine на Mac (хосте). Версия GCC — 5.4.
gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Код компилируется с помощью gcc, с включенным средством очистки адресов и неопределенным средством очистки ( -fsanitize=address,undefined
).
Кажется, что компилятор выдает инструкцию «ud2» при включении дезинфицирующих средств. Я хотел бы знать, является ли эта ошибка ошибкой компилятора, ошибкой дезинфицирующего средства или ошибкой кода?
Комментарии:
1. Одна из возможных причин заключается в том, что вы выполняете данные, например, из-за неправильного использования указателей на функции. Другое дело, что либо ваш код, либо библиотека неправильно скомпилированы или настроены для вашего процессора и используют инструкции, которые он не поддерживает. Числовой код, такой как gsl, Вероятно, использует расширения SIMD, такие как SSE, AVX и т. Д., Которые требуют достаточно нового процессора.
2. Один из способов проверки — запустить код в отладчике, таком как gdb, и при его сбое использовать
x/i $pc
для разборки инструкции с ошибкой. Проверьте руководство по архитектуре процессора на предмет того, какой набор функций требуется для этой инструкции, а затем посмотрите, есть ли у вашего процессора этот набор функций (с его руководством или / proc / cpuinfo или что-то еще).3. @NateEldredge Спасибо. Я обновил вопрос дополнительной информацией. В частности, кажется, что компилятор выдает инструкцию «ud2» при включении дезинфицирующих средств. Я хотел бы знать, является ли это ошибкой компилятора, ошибкой дезинфицирующего средства или ошибкой кода?
4. «Ошибка кода» обычно является разумной догадкой. Компилятор вставил бы инструкции ud2, когда какая-либо проверка на неопределенное поведение завершилась неудачей, или какой-либо путь кода никогда не должен быть достигнут. Учитывая код ошибки, моим первым предположением было бы
*nu
переполнение. Возможно, вам будет легче отлаживать это, если вы перекомпилируете без оптимизации.5. Вы также используете довольно старое программное обеспечение. Тестирование с более новыми версиями может помочь двумя способами: (1) это может быть ошибка в GSL, которая с тех пор была исправлена; (2) средство дезинфекции в более новом компиляторе может быть более полезным и с меньшей вероятностью иметь собственные ошибки.