URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 3123
[ Назад ]

Исходное сообщение
"free() рушит приложение при том что с памятью всё ок..."

Отправлено Serega_S , 04-Июл-04 15:49 
   Привет всем! Случилось страшное!!! Может быть конечно виноват я сам, но! В ниже приведённом коде free() вызывает Сегментэйшн фаулт. Проследил указатель - в норме, тобишь не изменяется (со времени выделения) и всё вроде пучком. Может быть это из-за того, что я делаю многопоточное приложение и нужно использовать специальные библиотеки... Но я уже -lpthread подключал - то же самое. Мож я что ещё забыл? Подмогните!
Вот код:
       tmp=(char*)malloc(m.len_data-m.adreses*sizeof(int)+1);
    if(!tmp)
    {
        set_log("next_connect",errno);
        return(void*)-1;
    }
    +
    *(pam+m.len_data-1+sizeof(int)*m.adreses)=0;
    sprintf(tmp,"%s:%s",adres,pam+m.adreses*sizeof(int));
    //update(tmp);
    free(tmp);

Вот пример отладки:

Breakpoint 1, next_connect (uk=0x8057100) at functions.cpp:381
381              tmp=(char*)malloc(m.len_data-m.adreses*sizeof(int)+1);
(gdb) watch tmp
Hardware watchpoint 2: tmp
(gdb) p tmp
$1 = 0x0
(gdb) n
Hardware watchpoint 2: tmp

Old value = 0x0
New value = 0x80860c8 "8??@?\211\a\bm\001"
next_connect (uk=0x8057100) at functions.cpp:382
382            if(!tmp)
(gdb)
388            *(pam+m.len_data-1+sizeof(int)*m
.adreses)=0;
(gdb)
389            sprintf(tmp,"%s:%s",adres,pam+m.adreses*sizeof(int));
(gdb)
391            free(tmp);
(gdb) p tmp
$2 = 0x80860c8 "10.0.0.1:Client connect!"
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x409b7c90 in chunk_free (ar_ptr=0x40a6b620, p=0x80860c0) at malloc.c:3231
3231    malloc.c: No such file or directory.
    in malloc.c
Current language:  auto; currently c

P.S.: Единственная мысть возникает - переход на системные функции выделения памяти (из-за подобных косяков под виндой пришлось так же поступить в своё время), но уж больно много кода лопатить. И за Линукс обидно - не винда ведь!!! ДОЛЖЕН работать - ведь на то он Линукс!


Содержание

Сообщения в этом обсуждении
"free() рушит приложение при том что с памятью всё ок..."
Отправлено ACCA , 04-Июл-04 19:27 
В таких случаях пробуй читать вслух в лицах:


> if(!tmp)
> {
>  set_log("next_connect",errno);
>  return(void*)-1;
> }
[...]
> free(tmp);

[...]
>next_connect (uk=0x8057100) at functions.cpp:382

Раз ты получил надпись "next_connect", значит у тебя tmp=0.


>391   free(tmp);

Ты сделал free на нулевой указатель.


>Program received signal SIGSEGV, Segmentation fault.

И получил segmentation fault (что определяется по тому, что 0 по адресу 0 больше не 0).


"free() рушит приложение при том что с памятью всё ок..."
Отправлено XMan , 04-Июл-04 19:37 
Я не являюсь знатоком gdb, но что-то мне подсказывает, что число 382 в строках:

next_connect (uk=0x8057100) at functions.cpp:382

и

382 if(!tmp)

обозначают одно и то же понятие - номер строки в исходнике. То есть, в этой строке расположен "if(!tmp)", что не является критичным.
Да и "next_connect" появляется не после "free", а перед "if".

Что я упустил из виду ?


"free() рушит приложение при том что с памятью всё ок..."
Отправлено Serega_S , 05-Июл-04 05:19 
>обозначают одно и то же понятие - номер строки в исходнике. То
>есть, в этой строке расположен "if(!tmp)", что не является критичным.
>Да и "next_connect" появляется не после "free", а перед "if".
>
>Что я упустил из виду ?

То что next_connect (uk=0x8057100) at functions.cpp:382 - это уведомление, что в этой строчке бряк и он сработал.
    Что-то все запутались с next_connect - это функция так называется. Если бы срабатывал if, то это было бы видно в листинге работы дебаггера (если его можно так назвать - листинг).

Вот так вот.

                                 С уважением, Сергей.



"free() рушит приложение при том что с памятью всё ок..."
Отправлено Serega_S , 05-Июл-04 03:09 
>next_connect (uk=0x8057100) at functions.cpp:382

>Раз ты получил надпись "next_connect", значит у тебя tmp=0.
next_connect - это так функция называется тоже, и на ней я поставил бряк

перед тем как выполнить free  я в дебаггере p tmp сделал - посмотрите получше - там всё видно.
>>391   free(tmp);
>
>Ты сделал free на нулевой указатель.

Я именно сделал упор+привёл листинг дебага что tmp НЕ МЕНЯЕТСЯ и он НЕ НУЛЕВОЙ.

>И получил segmentation fault (что определяется по тому, что 0 по адресу
>0 больше не 0).

Вот так. Читайте лучше вопрос - в хорошем вопросе содержится половина ответа. :-)))


"free() рушит приложение при том что с памятью всё ок..."
Отправлено XMan , 04-Июл-04 19:30 
Он и работает. И с потоками тоже. А если ты выдаляешь 10 байт и пишешь туда 11, то никакая ОС не спасет твоей программы, хотя нормальная ОС сама выживет :)
Числа приведены в качестве примера, ибо понять, колько ты выделяешь и сколько пишешь не предстваляется возможным.

Кроме того, не факт, что именно в этой переменной проблемы. Например, ты можешь устроить переполнение буфера где-то в начале программы, а зависнет внутренняя функция из библиотеки, например, постгреса, вызванная в одном из потоков через час работы этой самой программы.

---

Для проверки двойного free можешь перед компиляцией задать переменную окружения "MALLOC_CHECK_=1" и посмотреть, что программа будет орать на stderr. За подробностями "man malloc".


"free() рушит приложение при том что с памятью всё ок..."
Отправлено Serega_S , 05-Июл-04 05:37 
>Он и работает. И с потоками тоже. А если ты выдаляешь 10
>байт и пишешь туда 11, то никакая ОС не спасет твоей
>программы, хотя нормальная ОС сама выживет :)
>Числа приведены в качестве примера, ибо понять, колько ты выделяешь и сколько
>пишешь не предстваляется возможным.

Дык это лопатить весь код? А по-другому как-нибудь нельзя? Уж больно много лопатить... Может что-нибудь наподобии "MALLOC_CHECK_=1" есть?

>Кроме того, не факт, что именно в этой переменной проблемы. Например, ты
>можешь устроить переполнение буфера где-то в начале программы, а зависнет внутренняя
>функция из библиотеки, например, постгреса, вызванная в одном из потоков через
>час работы этой самой программы.

Кстати тоже там баг ещё один был - ни с того ни с сего падал QString string=... Причём тоже все параметры в порядке. И это происходило до описанной выше баги. Наверно это из той же оперы. Може есть какая-нибудь прога для отслеживания работы с памятью?

>Для проверки двойного free можешь перед компиляцией задать переменную окружения "MALLOC_CHECK_=1" и
Насчёт двойного фрии - по идее (хотя это в винде так было) - при очищении памяти, она обычно сразу забивается мусором. тобишь это было бы видно в дебаггере. И тем более это маленький кусочек кода - память только выделилась и тут же очистилась - это если только как-то в другом потоке очищается, но уж больно хитро. Хотя я естественно проверю.

>посмотреть, что программа будет орать на stderr. За подробностями "man malloc".
>
А точно не нужно подключать особенные библиотеки для многопоточного приложения? Под виндой нужно было.



"free() рушит приложение при том что с памятью всё ок..."
Отправлено XMan , 05-Июл-04 15:25 
> при очищении памяти, она обычно сразу забивается мусором. тобишь это было бы видно в дебаггере.

Обычно память ничем не забивается, а остается такой, какой она была на момент free. Прочто система отмечает у себя, что этот кусок памяти свободен и его можно будет кому-нибудь отдать по запросу.

Касательно автоматизации поиска ничего не могу сказать. Это как раз самая неприятная ошибка. Потому подавляющее большинство эксплоитов построены именно на переполнении буфера.


"free() рушит приложение при том что с памятью всё ок..."
Отправлено XMan , 05-Июл-04 15:29 
Или вот еще из той же оперы:

void func(void** param) {
  param* = malloc(.....);
  free(param*);
}
...

А теперь запускаем два потока, каждый из которых вызывает эту функцию и передает указатель на одну и ту же переменную.


"free() рушит приложение при том что с памятью всё ок..."
Отправлено qq , 05-Июл-04 12:48 
а вот интересно, ты самый простой вариант проверял?
сделай

printf("size of tmp: %d\n",m.len_data-m.adreses*sizeof(int)+1);

и перед самым free сделай

printf("strlen tmp: %d\n",strlen(tmp));

и сравни...