Ці сапраўды calloc () павольней, чым malloc (), таму што ён ініцыялізуе памяць да 0 і патрабуе часу, каб ініцыялізаваць, а malloc () не? Ці істотная розніца ў выкананні гэтых дзвюх функцый?


адказ 1:

calloc () ніколі не можа быць хутчэй, чым malloc () дзякуючы рэалізацыі calloc ().

Як вы ўжо згадвалі, calloc усталёўвае памяць у нуль, што можа заняць некаторы час. Але гэта сапраўды залежыць ад вашай аперацыйнай сістэмы. Калі ваша аперацыйная сістэма можа даць Calloc нулявыя старонкі, не трэба ўсталёўваць іх у нуль. Calloc таксама закранае памяць. Аперацыйная сістэма павінна фактычна знайсці падыходнае месца, перш чым выклік Calloc.

malloc можа вярнуцца хутчэй у Linux, бо ён не можа быць рэзервовае капіраванне з памяці, пакуль вы на самой справе не выкарыстоўваеце памяць. Linux робіць тое, што мы называем "аптымістычным размеркаваннем памяці". Гэта падобна на працэс капіравання падчас запісу, які Linux выкарыстоўвае пры разгалінаванні працэсу. Такім чынам, калі вы запусціце malloc (), вы атрымаеце доступ да віртуальнай памяці, але пры выкарыстанні гэтай памяці выдзяляюцца фактычныя старонкі.

Ці стварае malloc лянота фонавыя старонкі для адлюстравання пад Linux (і іншымі платформамі)?


адказ 2:

Як падкрэсліў Робін Томас, званок calloc () будзе ўсё больш павольным з-за кан'юнктурнага адлюстравання. Калі вы выдзяляеце 100 Мбайт і выкарыстоўваеце толькі першыя 4 КБ, ядро ​​вылучае толькі адну старонку рэальнай памяці ў віртуальнай адраснай прасторы. Звычайна гэта 4 Кб, але вы можаце выкарыстоўваць getpagesize (пустэчу), каб вызначыць памер старонкі для тыпаў Unix.

Калі вы пішаце тэставую праграму, якая выкарыстоўвае malloc для выдзялення 10000 блокаў, а потым calloc для выдзялення 10000 блокаў, calloc працуе павольней, таму што malloc не робіць нічога больш, чым дазволіць ядру стварыць віртуальную прастору для блокаў. Але calloc () прымушае ядро ​​прайсці праз кучу і знайсці неабходную яму памяць. Затым ён прызначае яго ў адраснай прасторы праграмы.

Калі ядро ​​адлюстроўвае новую памяць у віртуальнай адраснай прасторы, яно забівае яго, каб пераканацца, што вы не бачыце ніякіх дадзеных з іншай праграмы. Але як толькі вы выпусціце яго і прысвоіце яму той жа ці меншы памер, вы, верагодна, вернеце свой "стары" блок памяці, як паказана тут:

#include #include #include #include print_mem (int * mem) {int i; для (i = 0; i <100; i ++, mem ++) printf ("% x", * mem); } int main (пустата) {int * mem, i; printf ("Старонкі памяці ў гэтым архіве:% d \ n", getpagesize ()); // 100-цалёвы Malloc і запоўніце яго Deadbeef mem = malloc (100 * sizeof (int)); printf ("пераназначаны з malloc \ n"); print_mem (памяць); для (i = 0; i <100; i ++) * (mem + i) = 0xdeadbeef; printf ("\ nПасля прызначэння \ n"); print_mem (памяць); бясплатна (памяць); printf ("\ nFreed \ n"); mem = malloc (100 * sizeof (int)); printf ("\ nЗазначэнне іншага блока памяці аднолькавага памеру \ n"); // Гэта, хутчэй за ўсё, будзе ўтрымліваць 0xdeadbeef print_mem (mem); для (i = 0; i <100; i ++) * (mem + i) = 0xabbababe; printf ("\ nПасля прызначэння \ n"); print_mem (памяць); бясплатна (памяць); printf ("\ nFreed \ n"); }

Я на самай справе выкарыстоўваю glib для ўсяго размеркавання памяці, але ўсё яшчэ лічу g_malloc0 карысным, калі ведаю, што ўся памяць павінна быць роўная нулю. Але толькі тады. Я б выдаліў толькі выдзеленую памяць, калі ў мяне была б канкрэтная прычына.

Для праграм бяспекі мае сэнс усталяваць іх у нуль, перш чым выпусціць іх. Гэта гарантуе, што пры ўзлому праграмы ўстаўлены код не можа шукаць кучу і адлюстроўваць старыя дадзеныя, робячы вялікае адлюстраванне і проста праглядаючы (альбо адпраўляючы на ​​агляд).


адказ 3:

Як падкрэсліў Робін Томас, званок calloc () будзе ўсё больш павольным з-за кан'юнктурнага адлюстравання. Калі вы выдзяляеце 100 Мбайт і выкарыстоўваеце толькі першыя 4 КБ, ядро ​​вылучае толькі адну старонку рэальнай памяці ў віртуальнай адраснай прасторы. Звычайна гэта 4 Кб, але вы можаце выкарыстоўваць getpagesize (пустэчу), каб вызначыць памер старонкі для тыпаў Unix.

Калі вы пішаце тэставую праграму, якая выкарыстоўвае malloc для выдзялення 10000 блокаў, а потым calloc для выдзялення 10000 блокаў, calloc працуе павольней, таму што malloc не робіць нічога больш, чым дазволіць ядру стварыць віртуальную прастору для блокаў. Але calloc () прымушае ядро ​​прайсці праз кучу і знайсці неабходную яму памяць. Затым ён прызначае яго ў адраснай прасторы праграмы.

Калі ядро ​​адлюстроўвае новую памяць у віртуальнай адраснай прасторы, яно забівае яго, каб пераканацца, што вы не бачыце ніякіх дадзеных з іншай праграмы. Але як толькі вы выпусціце яго і прысвоіце яму той жа ці меншы памер, вы, верагодна, вернеце свой "стары" блок памяці, як паказана тут:

#include #include #include #include print_mem (int * mem) {int i; для (i = 0; i <100; i ++, mem ++) printf ("% x", * mem); } int main (пустата) {int * mem, i; printf ("Старонкі памяці ў гэтым архіве:% d \ n", getpagesize ()); // 100-цалёвы Malloc і запоўніце яго Deadbeef mem = malloc (100 * sizeof (int)); printf ("пераназначаны з malloc \ n"); print_mem (памяць); для (i = 0; i <100; i ++) * (mem + i) = 0xdeadbeef; printf ("\ nПасля прызначэння \ n"); print_mem (памяць); бясплатна (памяць); printf ("\ nFreed \ n"); mem = malloc (100 * sizeof (int)); printf ("\ nЗазначэнне іншага блока памяці аднолькавага памеру \ n"); // Гэта, хутчэй за ўсё, будзе ўтрымліваць 0xdeadbeef print_mem (mem); для (i = 0; i <100; i ++) * (mem + i) = 0xabbababe; printf ("\ nПасля прызначэння \ n"); print_mem (памяць); бясплатна (памяць); printf ("\ nFreed \ n"); }

Я на самай справе выкарыстоўваю glib для ўсяго размеркавання памяці, але ўсё яшчэ лічу g_malloc0 карысным, калі ведаю, што ўся памяць павінна быць роўная нулю. Але толькі тады. Я б выдаліў толькі выдзеленую памяць, калі ў мяне была б канкрэтная прычына.

Для праграм бяспекі мае сэнс усталяваць іх у нуль, перш чым выпусціць іх. Гэта гарантуе, што пры ўзлому праграмы ўстаўлены код не можа шукаць кучу і адлюстроўваць старыя дадзеныя, робячы вялікае адлюстраванне і проста праглядаючы (альбо адпраўляючы на ​​агляд).


адказ 4:

Як падкрэсліў Робін Томас, званок calloc () будзе ўсё больш павольным з-за кан'юнктурнага адлюстравання. Калі вы выдзяляеце 100 Мбайт і выкарыстоўваеце толькі першыя 4 КБ, ядро ​​вылучае толькі адну старонку рэальнай памяці ў віртуальнай адраснай прасторы. Звычайна гэта 4 Кб, але вы можаце выкарыстоўваць getpagesize (пустэчу), каб вызначыць памер старонкі для тыпаў Unix.

Калі вы пішаце тэставую праграму, якая выкарыстоўвае malloc для выдзялення 10000 блокаў, а потым calloc для выдзялення 10000 блокаў, calloc працуе павольней, таму што malloc не робіць нічога больш, чым дазволіць ядру стварыць віртуальную прастору для блокаў. Але calloc () прымушае ядро ​​прайсці праз кучу і знайсці неабходную яму памяць. Затым ён прызначае яго ў адраснай прасторы праграмы.

Калі ядро ​​адлюстроўвае новую памяць у віртуальнай адраснай прасторы, яно забівае яго, каб пераканацца, што вы не бачыце ніякіх дадзеных з іншай праграмы. Але як толькі вы выпусціце яго і прысвоіце яму той жа ці меншы памер, вы, верагодна, вернеце свой "стары" блок памяці, як паказана тут:

#include #include #include #include print_mem (int * mem) {int i; для (i = 0; i <100; i ++, mem ++) printf ("% x", * mem); } int main (пустата) {int * mem, i; printf ("Старонкі памяці ў гэтым архіве:% d \ n", getpagesize ()); // 100-цалёвы Malloc і запоўніце яго Deadbeef mem = malloc (100 * sizeof (int)); printf ("пераназначаны з malloc \ n"); print_mem (памяць); для (i = 0; i <100; i ++) * (mem + i) = 0xdeadbeef; printf ("\ nПасля прызначэння \ n"); print_mem (памяць); бясплатна (памяць); printf ("\ nFreed \ n"); mem = malloc (100 * sizeof (int)); printf ("\ nЗазначэнне іншага блока памяці аднолькавага памеру \ n"); // Гэта, хутчэй за ўсё, будзе ўтрымліваць 0xdeadbeef print_mem (mem); для (i = 0; i <100; i ++) * (mem + i) = 0xabbababe; printf ("\ nПасля прызначэння \ n"); print_mem (памяць); бясплатна (памяць); printf ("\ nFreed \ n"); }

Я на самай справе выкарыстоўваю glib для ўсяго размеркавання памяці, але ўсё яшчэ лічу g_malloc0 карысным, калі ведаю, што ўся памяць павінна быць роўная нулю. Але толькі тады. Я б выдаліў толькі выдзеленую памяць, калі ў мяне была б канкрэтная прычына.

Для праграм бяспекі мае сэнс усталяваць іх у нуль, перш чым выпусціць іх. Гэта гарантуе, што пры ўзлому праграмы ўстаўлены код не можа шукаць кучу і адлюстроўваць старыя дадзеныя, робячы вялікае адлюстраванне і проста праглядаючы (альбо адпраўляючы на ​​агляд).