Как найти место переполнения буфера и повреждений памяти?

valgrind не может найти ничего полезного. Я смущен.

Симптомы:

  1. мои данные повреждены вызовом malloc ()
  2. обратный адрес моей функции заменен чем-то неправильным

PS: код НЕ segfault

В настоящее время у меня есть некоторый прогресс, заменив все мои malloc () на _1 _ + _ 2_


person vitaly.v.ch    schedule 21.02.2011    source источник
comment
может быть, вы могли бы предоставить хотя бы несколько строк кода? иначе никто не сможет вам помочь.   -  person eckes    schedule 21.02.2011
comment
Исправьте все ошибки, и это должно решить эту проблему. [/сарказм]   -  person Lundin    schedule 21.02.2011
comment
Пожалуйста, предоставьте хотя бы некоторую информацию. Какой симптом вы видите? Ошибка сегментации? Повреждение данных? Что ты пробовал? Какие были результаты? Если вы не приложите усилий для ответа на свой вопрос, как вы ожидаете, что мы на него ответим?   -  person thkala    schedule 21.02.2011


Ответы (6)


Возможно, вы перезаписываете стек или кучу.

Вы можете попробовать добавить флаг -fstack-protector-all в свой Параметры командной строки GCC для запроса встроенных в программу отчетов о разбиении стека. Это может привести к более раннему выходу из строя.

Другая возможность - посмотреть адрес, указанный в dmesg выводе, и посмотреть, не можете ли вы отследить функцию / память, которая была разбита:

[68303.941351] broken[13301]: segfault at 7f0061616161 ip 000000000040053d sp 00007fffd4ad3980 error 4 in broken[400000+1000]

readelf -s сбросит таблицу символов, мы можем найти функцию, которая вызывает проблему:

$ readelf -s broken | grep 4005
40: 00000000004005e0     0 FUNC    LOCAL  DEFAULT   13 __do_global_ctors_aux
47: 0000000000400540     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
57: 0000000000400550   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
63: 0000000000400515    42 FUNC    GLOBAL DEFAULT   13 main

Процедура main выполняется, когда используется неверный указатель:

#include <string.h>

void f(const char *s) {
    char buf[4];
    strcpy(buf, s);
    return;
}

int main(int argc, char* argv[]) {
    f("aaaa");
    f("aaaaaaaaaaaaaaaaaaaa");
    return 0;
}

Когда main пытается вернуться в библиотеку C для выхода, он использует неверный указатель, хранящийся в кадре стека. Итак, посмотрите на функции, вызываемые main, и (в этом тривиальном случае это довольно просто) f, очевидно, тот жук, который нацарапал весь фрейм стека.

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

person sarnold    schedule 21.02.2011
comment
Я уже использую -fstack-protect-all, но на данный момент это не дает никакого полезного результата. - person vitaly.v.ch; 21.02.2011
comment
@ vitaly.v.ch, я тоже был разочарован. StackGuard мог это уловить, патч ProPolice, который, в конечном итоге, исключила команда GCC, был довольно умным в отношении того, какие процедуры «нуждаются в защите»; Я надеялся, что вариант -all исправит это ... - person sarnold; 21.02.2011
comment
@ vitaly.v.ch, когда я отправил отчет об ошибке -fstack-protect-all в Ubuntu, он был помечен как дубликат эта ошибка, в которой упоминается патч в версии gcc-4.4 Natty: debian/patches/gcc-default-ssp.patch. Надеюсь, это поможет вам установить фиксированную версию GCC на свой Slack. - person sarnold; 22.02.2011
comment
Согласно результатам проверки на усиление, у моего gcc нет этой ошибки. - person vitaly.v.ch; 22.02.2011

Valgrind memcheck не очень хорошо обнаруживает переполнение буфера. Но вы можете попробовать патч, который может.

person onemasse    schedule 21.02.2011

  1. Исправить все висячие указатели, все переполнения буфера
  2. Используйте указатели только там, где они действительно нужны

см. следующую ссылку :: Какие инструменты C / C ++ могут проверять переполнение буфера?

person Manish Trivedi    schedule 21.02.2011
comment
висячие указатели уже исправлены, но мне нужно руководство, чтобы найти место переполнения буфера - person vitaly.v.ch; 21.02.2011

Вы также можете попробовать пробную версию IBM Rational Purify - довольно хороший инструмент для обнаружения переполнения буфера, утечек памяти и любых других ошибок повреждения памяти. Перейдите по этой ссылке, чтобы загрузить http://www-01.ibm.com/software/awdtools/purify/unix/

person Subbu    schedule 21.02.2011
comment
в моем случае это бесполезно - я отлаживаю разделяемую библиотеку с предварительно скомпилированным приложением. - person vitaly.v.ch; 21.02.2011

В какой среде вы работаете?

Если вы разрабатываете в Windows, попробуйте эту статью http://msdn.microsoft.com/en-us/library/cc500347.aspx

person Nocturnal    schedule 21.02.2011
comment
Я не писал собственного кода для Linux, но знаю, что наиболее распространенные строковые функции устарели из-за атак на переполнение буфера. Вы должны проверить, являются ли они защищенными версиями каких-либо желаемых строк, которые вы хотите использовать, если таковых нет, вы можете написать свою собственную версию. Просто проверив целевой буфер и убедившись, что он больше, чем исходный буфер. - person Nocturnal; 21.02.2011
comment
Я не использую строковые функции - person vitaly.v.ch; 21.02.2011

Не могу вам помочь в Linux. Но вы говорите, что не используете никаких строковых функций, что говорит о том, что ваше приложение может быть довольно переносимым. А под виндой не работает?

Если это так, наш инструмент CheckPointer может найти проблему. Он выполняет гораздо более тщательную проверку того, как ваша программа использует указатели, чем Valgrind, потому что он может видеть структуру и объявления в вашем коде, и он понимает различные виды использования хранилища (кадры стека против кучи). Valgrind видит только машинные инструкции и не может сказать, когда кадры стека выходят за пределы области видимости.

person Ira Baxter    schedule 08.07.2011