Осматривая разборку нижеследующей функции,
void * malloc_float_align(size_t n, unsigned int a, float *& dizi)
{
void * adres=NULL;
void * adres2=NULL;
adres=malloc(n*sizeof(float)+a);
size_t adr=(size_t)adres;
size_t adr2=adr+a-(adr&(a-1u));
adres2=(void * ) adr2;
dizi=(float *)adres2;
return adres;
}
Встроенные функции не встроены даже при inline
флаг оптимизации установлен.
; Line 26
$LN4:
push rbx
sub rsp, 32 ; 00000020H
; Line 29
mov ecx, 160 ; 000000a0H
mov rbx, r8
call QWORD PTR __imp_malloc <------this is not inlined
; Line 31
mov rcx, rax
; Line 33
mov rdx, rax
and ecx, 31
sub rdx, rcx
add rdx, 32 ; 00000020H
mov QWORD PTR [rbx], rdx
; Line 35
add rsp, 32 ; 00000020H
pop rbx
ret 0
Вопрос: это обязательное свойство таких функций, как malloc
? Можем ли мы встроить его каким-то образом для проверки (или любой другой функции, такой как strcmp / new / free / delete)? Это запрещено?
Как правило, компилятор встроит функции, когда у него есть исходный код, доступный во время компиляции (другими словами, функция определена, а не просто объявление прототипа) в заголовочном файле).
Однако в этом случае функция (malloc
) находится в DLL, поэтому очевидно, что исходный код не доступен компилятору во время компиляции вашего кода. Это не имеет ничего общего с тем, что malloc
делает (и т. д.). Тем не менее, также вероятно, что malloc
в любом случае не будет встроенным, так как это довольно большая функция (по крайней мере, часто), что предотвращает ее вставку, даже если доступен исходный код.
Если вы используете Visual Studio, вы почти наверняка сможете найти исходный код для вашей библиотеки времени выполнения, так как он поставляется с пакетом Visual Studio.
(Функции времени выполнения C находятся в DLL, потому что многие различные программы в системе используют одни и те же функции, поэтому помещение их в DLL, которая загружается один раз для всех «пользователей» функциональности, даст хорошую экономию на размере всех код в системе. Хотя malloc, возможно, только несколько сотен байт, функция, как printf
можно легко добавить около 5-25 КБ к размеру исполняемого файла. Умножьте это на количество «пользователей» printf
и, вероятно, несколько сотен килобайт только из этой «функции» «спасены» — и, конечно, все другие функции, такие как fopen
, fclose
, malloc
, calloc
, free
и так далее все по чуть-чуть добавляют к общему размеру)
Компилятор C может быть встроенным malloc
(или, как вы видите в своем примере, часть этого), но это не так требуется встроить что-нибудь. Используемые им эвристики не должны документироваться, и они, как правило, довольно сложные, но обычно в них встроены только короткие функции, так как в противном случае возможен взлёт кода.
malloc
и друзья реализованы в библиотеке времени выполнения, поэтому они не доступны для встраивания. Для этого им нужно иметь свою реализацию в заголовочных файлах.
Если вы хотите увидеть их разборки, вы можете войти в них с помощью отладчика. Или, в зависимости от используемого компилятора и среды выполнения, исходный код может быть доступен. Например, он доступен как для gcc, так и для msvc.
Главное, остановить обтекание malloc()
и др. это их сложность — и очевидный факт, что никакого встроенного определения функции не предусмотрено. Кроме того, вам могут понадобиться разные версии функции в разное время; было бы сложнее (грязнее) для таких инструментов, как valgrind
работать, и вы не можете договориться об использовании отладочной версии функций, если их код встроен.