>>Всем привет! У меня такой вопрос: 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 - откомпилируйте плиз в ассемблер эту прогу и выложите сюда.