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

Исходное сообщение
"free()"

Отправлено landor , 06-Фев-06 18:31 
Всем привет! У меня такой вопрос: free() из стандартной библиотеки игнорирует нулевой параметр, те структура всей динамики не нарушится? По моим экспериментам - нет, но хотелась бы услышать точное утверждение, так  спокойнее... И еще, тоже для спортивного интереса, почему, если в самом начале кода воткнуть malloc_stats(), то на нем вываливается segmentation fault?
А после первого malloc() все нормально. Заранее благодарю.

Содержание

Сообщения в этом обсуждении
"free()"
Отправлено horsh , 06-Фев-06 20:03 
>Всем привет! У меня такой вопрос: free() из стандартной библиотеки игнорирует нулевой
>параметр, те структура всей динамики не нарушится? По моим экспериментам -
>нет, но хотелась бы услышать точное утверждение, так  спокойнее...

man -s 3 free (или man free)

содержит все необходимые точные утверждения


"free()"
Отправлено BsDr , 07-Фев-06 10:17 

http://www.opennet.me/openforum/vsluhforumID9/4693.html

На самом деле free() такая непредсказуемая штука.
Ругается там где не должна, не ругается там где должна и при этом как-то еще умудряется работать.


"free()"
Отправлено Hordi , 07-Фев-06 10:30 
>На самом деле free() такая непредсказуемая штука.
Какая непредсказуемая? При чем здесь тот топик? Почитайте доку по glibc или по ядру - никаких вопросов по управлению памяти не возникнет - все четко!


"free()"
Отправлено BsDr , 07-Фев-06 10:49 
>никаких вопросов по управлению памяти не возникнет -
>все четко!

Если у вас вопросов не возникало это вовсе не означает что их нет.
top в FreeBsd: http://bsdportal.ru/fdocs/books/handbook/basics-processes.html


"free()"
Отправлено Hordi , 07-Фев-06 11:09 
>top в FreeBsd: http://bsdportal.ru/fdocs/books/handbook/basics-processes.html
И что из этого? Это же не говорит о том, что освобожденная память не может быть использована другим процессом. Выделите в процессе под максимум памяти, затем освободите и заблокируйте программу, запустите другую такую-же программу - все будет работать, и памяти хватит.


"free()"
Отправлено BsDr , 07-Фев-06 11:33 
Мы говорим о разных вещах. Свою тему в форуме я предложил как пример неправильного поведения функции free() в FreeBsd.
Правилнее даже сказать о  отображении количества памяти в системе при выделении и при освобождении.



"free()"
Отправлено Forth , 07-Фев-06 12:38 
>Мы говорим о разных вещах. Свою тему в форуме я предложил как
>пример неправильного поведения функции free() в FreeBsd.
>Правилнее даже сказать о  отображении количества памяти в системе при выделении
>и при освобождении.
free,  malloc работает с кучей. А выделение памяти происходит вызом sbrk, то есть увеличением сегмента data.
И поведение в принципе правильное, освобождение памяти идет, но только в куче, а не путем системных вызовов, и делается это для минимизации переключения контекста, так что правильно это или нет - но что ускоряет работу malloc, free весьма существенно - это да. Все равно подсистема виртуальной памяти достаточно интеллектуальна и выделяет страницы, только если они реально нужны. И отображается все правильно. reserved - это сколько запрошено приложением, а уже сколько реально используется - это совсем другое значение.


"free()"
Отправлено dimus , 07-Фев-06 10:25 
>>Всем привет! У меня такой вопрос: free() из стандартной библиотеки игнорирует нулевой
>>параметр, те структура всей динамики не нарушится? По моим экспериментам -
>>нет, но хотелась бы услышать точное утверждение, так  спокойнее...
>
>man -s 3 free (или man free)
>
>содержит все необходимые точные утверждения

В мане из линукс написано, что все будет пучком, однако, по-моему, последнее дело - полагаться на ман, так как в разных системах реализация может различаться. Лучше из параноидальных соображений считать, что при попытке освободить нулевой указатель при помощи free произойдет что-то нехорошее, и проверять это дело. Кода на это уйдет пара инструкций, так что много на этом вы не потеряете, а надежность увеличится.
Вызов без проверки:
int     main( int argc, char* argv[] )
{
        char*   ptr;

        ptr = (char*)malloc(10);
        free( ptr );
        return  0;
}
====================
// gcc -S freetest.c
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax
        subl    %eax, %esp
        subl    $12, %esp
        pushl   $10
        call    malloc
        addl    $16, %esp
        movl    %eax, -4(%ebp)
        subl    $12, %esp
        pushl   -4(%ebp)
        call    free
        addl    $16, %esp
        movl    $0, %eax
        leave
        ret
====================
// gcc -S -O2 freetest.c
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp    // Компилятор - идиот :(
        andl    $-16, %esp
        subl    $12, %esp
        pushl   $10
        call    malloc
        movl    %eax, (%esp)
        call    free
        movl    %ebp, %esp
        xorl    %eax, %eax
        popl    %ebp
        ret
====================
Вызов с проверкой:
int     main( int argc, char* argv[] )
{
        char*   ptr;

        ptr = (char*)malloc(10);
        if( ptr )
        {
                free( ptr );
        }
        return  0;
}
==================
// gcc -S freetest.c
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax       // Пипец
        subl    %eax, %esp
        subl    $12, %esp
        pushl   $10
        call    malloc
        addl    $16, %esp
        movl    %eax, -4(%ebp)
        cmpl    $0, -4(%ebp)   // Хреновая конструкция
        je      .L2
        subl    $12, %esp
        pushl   -4(%ebp)
        call    free
        addl    $16, %esp
.L2:
        movl    $0, %eax
        leave
        ret
====================
//  gcc -S -O2 freetest.c
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp     // "Крутая" оптимизация
        andl    $-16, %esp
        subl    $12, %esp
        pushl   $10
        call    malloc
        addl    $16, %esp
        testl   %eax, %eax   // А вот это по нашему, хотя я бы сделал
                             // немного не так
        jne     .L3
.L2:
        movl    %ebp, %esp
        xorl    %eax, %eax
        popl    %ebp
        ret
        .p2align 4,,15
.L3:
        subl    $12, %esp
        pushl   %eax
        call    free
        addl    $16, %esp
        jmp     .L2
====================

Из вышеприведенных листингов видно, что добавление проверки оказывает мало влияния на результирующий код, гораздо больше на него влияет включение оптимизации. Хотя порою компилятор откровенно тупит :(

bash-3.00$ gcc --version
gcc (GCC) 3.3.4
Copyright (C) 2003 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 4 - откомпилируйте плиз в ассемблер эту прогу и выложите сюда.


"free()"
Отправлено Hordi , 07-Фев-06 11:12 
>В мане из линукс написано, что все будет пучком, однако, по-моему, последнее
>дело - полагаться на ман, так как в разных системах реализация

Это первое дело, второе - полагаться на стандарт (или наборот). В стандарте сказано, что free проверяет на 0 параметр, поэтому любая самостоятельная проверка - это дублирование функционала. Даже компиляторы 10-летней давности все это делали (за все ручаться не могу, работал на нескольких)


"free()"
Отправлено landor , 07-Фев-06 17:50 
Дело в том, что в моём случае нужна предельная скорость, причем этих проверок мне надо будет навтавлять до черта(не в каждоу строке, естесственно, мест-то мало, зато в циклах и прочих узких местах, потому что у меня бешеные навороченые списки). А может лучше подскажете откуда взять исходники этих ф-й или может библиотtку как-нить дизассемблировать, там наверное хрень полная получится?

"free()"
Отправлено Wulf , 07-Фев-06 18:19 
>Дело в том, что в моём случае нужна предельная скорость, причем этих
>проверок мне надо будет навтавлять до черта(не в каждоу строке, естесственно,
>мест-то мало, зато в циклах и прочих узких местах, потому что
>у меня бешеные навороченые списки).

Я думаю для предельной скорости, Вам нужно придумать как применить какие-либо более эффективные структуры, нежели "бешеные навороченые списки". Может быть что-нибудь типа банальных красно-черных деревьев, хешей и иже с ними, зависит от задачи. А иначе, толку от микрооптимизации не будет. А библиотеки дизассемблировать не нужно смотрите исходники осей, благо они доступны


"free()"
Отправлено landor , 07-Фев-06 18:26 
>смотрите исходники осей, благо они доступны

А что там теже ф-и? Раньше сомневался в этом, спасибо если так.

>Может быть что-нибудь типа банальных красно-черных деревье
А списки у меня красивые, очень..., простите за нескромность. Я занимаюсь разработкой алгоритма трансляции С++ - какой бы список не был тр*ся он по-полной ;)


"free()"
Отправлено landor , 07-Фев-06 18:32 
У меня ещё вопросик: кто-нибудь юзал malloc_get_state(), malloc_set_state(), стабильно работает? Протестировать всё сложно, но вроде нормально. И ещё (просто ловлю баг с памятью в 10тыс стр кода, нашел около 5, кроме его самого ;\) я юзаю gcc 3.2.2 - это что дей-о так страшно. Говорят у него кодогенерация кривая, в каких случаях, сто именно криво? (знаю, знаю, виноват - лень не дает толком обновлять даже такие вещи)

"free()"
Отправлено Hordi , 07-Фев-06 18:42 
>сложно, но вроде нормально. И ещё (просто ловлю баг с памятью
>в 10тыс стр кода, нашел около 5, кроме его самого ;\)
>я юзаю gcc 3.2.2 - это что дей-о так страшно. Говорят
>у него кодогенерация кривая, в каких случаях, сто именно криво? (знаю,
>знаю, виноват - лень не дает толком обновлять даже такие вещи)
>
С уверенностью в 99.99999% могу сказать, что проблема в твоем коде, а не в компиляторе! Если бы в этих БАЗОВЫХ функциях были ошибки, то linux,freebsd и т.п. никогда бы не работали.



"free()"
Отправлено landor , 07-Фев-06 18:51 
>С уверенностью в 99.99999% могу сказать, что проблема в твоем коде, а
>не в компиляторе! Если бы в этих БАЗОВЫХ функциях были ошибки,
>то linux,freebsd и т.п. никогда бы не работали.

Ты знаешь, c уверенностью добавлю к твоим 99.99999% еще 199% ;)
Тем более, что уже нашел! Видел бы ты мою счастливую физиономию!
Естесственно ошибка как всегда: глупее не придумаешь ;\
Читал, кстати, теорию ошибо Мёрфи - 100% достоверная вещь!


"free()"
Отправлено Hordi , 07-Фев-06 18:54 
хорошо... когда хорошо.



"free()"
Отправлено landor , 07-Фев-06 18:54 
Нет а всё-таки что там с кривой кодогенерацией было версий 3.2.x gcc? А то написли кой-где, что все плохо, скачали, а мне лень! Может и не стоит?!

"free()"
Отправлено Hordi , 08-Фев-06 10:19 
>Нет а всё-таки что там с кривой кодогенерацией было версий 3.2.x gcc?
При выходе каждой новой версии имеется changelog. Зайди на сайт и посмотри список изменений