Всем привет! У меня такой вопрос: free() из стандартной библиотеки игнорирует нулевой параметр, те структура всей динамики не нарушится? По моим экспериментам - нет, но хотелась бы услышать точное утверждение, так спокойнее... И еще, тоже для спортивного интереса, почему, если в самом начале кода воткнуть malloc_stats(), то на нем вываливается segmentation fault?
А после первого malloc() все нормально. Заранее благодарю.
>Всем привет! У меня такой вопрос: free() из стандартной библиотеки игнорирует нулевой
>параметр, те структура всей динамики не нарушится? По моим экспериментам -
>нет, но хотелась бы услышать точное утверждение, так спокойнее...man -s 3 free (или man free)
содержит все необходимые точные утверждения
http://www.opennet.me/openforum/vsluhforumID9/4693.htmlНа самом деле free() такая непредсказуемая штука.
Ругается там где не должна, не ругается там где должна и при этом как-то еще умудряется работать.
>На самом деле free() такая непредсказуемая штука.
Какая непредсказуемая? При чем здесь тот топик? Почитайте доку по glibc или по ядру - никаких вопросов по управлению памяти не возникнет - все четко!
>никаких вопросов по управлению памяти не возникнет -
>все четко!Если у вас вопросов не возникало это вовсе не означает что их нет.
top в FreeBsd: http://bsdportal.ru/fdocs/books/handbook/basics-processes.html
>top в FreeBsd: http://bsdportal.ru/fdocs/books/handbook/basics-processes.html
И что из этого? Это же не говорит о том, что освобожденная память не может быть использована другим процессом. Выделите в процессе под максимум памяти, затем освободите и заблокируйте программу, запустите другую такую-же программу - все будет работать, и памяти хватит.
Мы говорим о разных вещах. Свою тему в форуме я предложил как пример неправильного поведения функции free() в FreeBsd.
Правилнее даже сказать о отображении количества памяти в системе при выделении и при освобождении.
>Мы говорим о разных вещах. Свою тему в форуме я предложил как
>пример неправильного поведения функции free() в FreeBsd.
>Правилнее даже сказать о отображении количества памяти в системе при выделении
>и при освобождении.
free, malloc работает с кучей. А выделение памяти происходит вызом sbrk, то есть увеличением сегмента data.
И поведение в принципе правильное, освобождение памяти идет, но только в куче, а не путем системных вызовов, и делается это для минимизации переключения контекста, так что правильно это или нет - но что ускоряет работу malloc, free весьма существенно - это да. Все равно подсистема виртуальной памяти достаточно интеллектуальна и выделяет страницы, только если они реально нужны. И отображается все правильно. reserved - это сколько запрошено приложением, а уже сколько реально используется - это совсем другое значение.
>>Всем привет! У меня такой вопрос: 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 проверяет на 0 параметр, поэтому любая самостоятельная проверка - это дублирование функционала. Даже компиляторы 10-летней давности все это делали (за все ручаться не могу, работал на нескольких)
Дело в том, что в моём случае нужна предельная скорость, причем этих проверок мне надо будет навтавлять до черта(не в каждоу строке, естесственно, мест-то мало, зато в циклах и прочих узких местах, потому что у меня бешеные навороченые списки). А может лучше подскажете откуда взять исходники этих ф-й или может библиотtку как-нить дизассемблировать, там наверное хрень полная получится?
>Дело в том, что в моём случае нужна предельная скорость, причем этих
>проверок мне надо будет навтавлять до черта(не в каждоу строке, естесственно,
>мест-то мало, зато в циклах и прочих узких местах, потому что
>у меня бешеные навороченые списки).Я думаю для предельной скорости, Вам нужно придумать как применить какие-либо более эффективные структуры, нежели "бешеные навороченые списки". Может быть что-нибудь типа банальных красно-черных деревьев, хешей и иже с ними, зависит от задачи. А иначе, толку от микрооптимизации не будет. А библиотеки дизассемблировать не нужно смотрите исходники осей, благо они доступны
>смотрите исходники осей, благо они доступныА что там теже ф-и? Раньше сомневался в этом, спасибо если так.
>Может быть что-нибудь типа банальных красно-черных деревье
А списки у меня красивые, очень..., простите за нескромность. Я занимаюсь разработкой алгоритма трансляции С++ - какой бы список не был тр*ся он по-полной ;)
У меня ещё вопросик: кто-нибудь юзал malloc_get_state(), malloc_set_state(), стабильно работает? Протестировать всё сложно, но вроде нормально. И ещё (просто ловлю баг с памятью в 10тыс стр кода, нашел около 5, кроме его самого ;\) я юзаю gcc 3.2.2 - это что дей-о так страшно. Говорят у него кодогенерация кривая, в каких случаях, сто именно криво? (знаю, знаю, виноват - лень не дает толком обновлять даже такие вещи)
>сложно, но вроде нормально. И ещё (просто ловлю баг с памятью
>в 10тыс стр кода, нашел около 5, кроме его самого ;\)
>я юзаю gcc 3.2.2 - это что дей-о так страшно. Говорят
>у него кодогенерация кривая, в каких случаях, сто именно криво? (знаю,
>знаю, виноват - лень не дает толком обновлять даже такие вещи)
>
С уверенностью в 99.99999% могу сказать, что проблема в твоем коде, а не в компиляторе! Если бы в этих БАЗОВЫХ функциях были ошибки, то linux,freebsd и т.п. никогда бы не работали.
>С уверенностью в 99.99999% могу сказать, что проблема в твоем коде, а
>не в компиляторе! Если бы в этих БАЗОВЫХ функциях были ошибки,
>то linux,freebsd и т.п. никогда бы не работали.Ты знаешь, c уверенностью добавлю к твоим 99.99999% еще 199% ;)
Тем более, что уже нашел! Видел бы ты мою счастливую физиономию!
Естесственно ошибка как всегда: глупее не придумаешь ;\
Читал, кстати, теорию ошибо Мёрфи - 100% достоверная вещь!
хорошо... когда хорошо.
Нет а всё-таки что там с кривой кодогенерацией было версий 3.2.x gcc? А то написли кой-где, что все плохо, скачали, а мне лень! Может и не стоит?!
>Нет а всё-таки что там с кривой кодогенерацией было версий 3.2.x gcc?
При выходе каждой новой версии имеется changelog. Зайди на сайт и посмотри список изменений