Однажды у нас была ошибка, которая не позволяла использовать обычные методы: valgrind, cleany и т. Д. Авария происходила только на машинах с большим объемом памяти и только на больших наборах входных данных.
В конце концов мы отследили его, используя точки наблюдения отладчика. Я постараюсь описать процедуру здесь:
1) Найти причину сбоя. Из вашего примера кода видно, что память для «exampleString» повреждена и поэтому не может быть записана. Давайте продолжим с этим предположением.
2) Установите точку останова в последнем известном месте, где «exampleString» используется или изменяется без проблем.
3) Добавить точку наблюдения к элементу данных exampleString. В моей версии g ++ строка хранится в _M_dataplus._M_p
. Мы хотим знать, когда этот элемент данных изменяется. Техника GDB для этого:
(gdb) p &exampleString._M_dataplus._M_p
$3 = (char **) 0xbfccc2d8
(gdb) watch *$3
Hardware watchpoint 1: *$3
Я, очевидно, здесь использую linux с g ++ и gdb, но я считаю, что точки наблюдения за памятью доступны большинству отладчиков.
4) Продолжайте, пока не сработает точка наблюдения:
Continuing.
Hardware watchpoint 2: *$3
Old value = 0xb7ec2604 ""
New value = 0x804a014 ""
0xb7e70a1c in std::string::_M_mutate () from /usr/lib/libstdc++.so.6
(gdb) where
Команда gdb where
выдаст обратную трассировку, показывающую, что привело к модификации. Это либо совершенно легальная модификация, в этом случае просто продолжайте - или, если вам повезет, это будет модификация из-за повреждения памяти. В последнем случае вы теперь сможете просмотреть код, который действительно вызывает проблему, и, надеюсь, решить ее.
Причиной нашей ошибки был доступ к массиву с отрицательным индексом. Индекс был результатом приведения указателя на int по модулю размера массива. Ошибка была пропущена Valgrind и соавт. поскольку адреса памяти, выделенные при работе с этими инструментами, никогда не равнялись "> MAX_INT
" и поэтому никогда не приводили к отрицательному индексу.