| malloc(3) | Library Functions Manual | malloc(3) |
الاسم¶
malloc, free, calloc, realloc, reallocarray - تخصيص وتحرير الذاكرة الديناميكية
المكتبة¶
مكتبة سي المعيارية (libc، -lc)
موجز¶
#include <stdlib.h>
void *malloc(size_t size); void free(void *_Nullable ptr); void *calloc(size_t nmemb, size_t size); void *realloc(void *_Nullable ptr, size_t size); void *reallocarray(void *_Nullable ptr, size_t nmemb, size_t size);
reallocarray():
منذ glibc 2.29:
_DEFAULT_SOURCE
glibc 2.28 وما قبله:
_GNU_SOURCE
الوصف¶
malloc()¶
تخصص الدالة malloc() size بايت وتُعيد مؤشرًا إلى الذاكرة المخصصة. الذاكرة غير مهيأة. إذا كان size يساوي 0، تُعيد malloc() قيمة مؤشر فريدة يمكن تمريرها لاحقًا بنجاح إلى free(). (انظر "سلوك غير محمول" لمشكلات قابلية النقل.)
free()¶
الدالة free() تُحرر مساحة الذاكرة المُشار إليها بواسطة ptr، والتي يجب أن تكون قد أُعيدت بواسطة استدعاء سابق لـ malloc() أو دوال ذات صلة. وإلا، أو إذا كان ptr قد حُرر بالفعل، يحدث سلوك غير مُحدد. إذا كان ptr هو NULL، لا يُنفذ أي عملية.
calloc()¶
الدالة calloc() تُخصص ذاكرة لمصفوفة من nmemb عنصرًا، كل منها بحجم size بايت، وتُعيد مؤشرًا إلى الذاكرة المُخصصة. تُضبط الذاكرة إلى الصفر. إذا كان nmemb أو size يساوي 0، فإن calloc() تُعيد قيمة مؤشر فريدة يمكن تمريرها لاحقًا بنجاح إلى free().
إذا أدى ضرب nmemb و size إلى تجاوز عدد صحيح، فإن calloc() تُعيد خطأ. على النقيض، لا يُكتشف تجاوز عدد صحيح في الاستدعاء التالي لـ malloc()، مما يؤدي إلى تخصيص كتلة ذاكرة بحجم غير صحيح:
malloc(nmemb * size);
realloc()¶
الدالة realloc() تُغير حجم كتلة الذاكرة المُشار إليها بواسطة ptr إلى size بايت. تبقى محتويات الذاكرة دون تغيير في النطاق من بداية المنطقة حتى الحد الأدنى للحجمين القديم والجديد. إذا كان الحجم الجديد أكبر من الحجم القديم، فإن الذاكرة المُضافة لا تُهيأ.
إذا كان ptr هو NULL، فإن الاستدعاء يُعادل malloc(size)، لجميع قيم size.
إذا كان size يساوي صفرًا، و ptr ليس NULL، فإن الاستدعاء يُعادل free(ptr) (ولكن انظر "سلوك غير محمول" لمشكلات قابلية النقل).
ما لم يكن ptr هو NULL، يجب أن يكون قد أُعيد بواسطة استدعاء سابق لـ malloc أو دوال ذات صلة. إذا نُقلت المنطقة المُشار إليها، يُنفذ free(ptr).
reallocarray()¶
الدالة reallocarray() تُغير حجم (وربما تنقل) كتلة الذاكرة المُشار إليها بواسطة ptr لتكون كبيرة بما يكفي لمصفوفة من nmemb عنصرًا، كل منها بحجم size بايت. تُعادل الاستدعاء
realloc(ptr, nmemb * size);
لكن، على عكس استدعاء realloc() ذلك، تفشل reallocarray() بأمان في حالة حدوث فائض في الضرب. إذا حدث مثل هذا الفائض، تُرجع reallocarray() خطأ.
قيمة الإرجاع¶
تُرجع دوال malloc() وcalloc() وrealloc() وreallocarray() مؤشرًا إلى الذاكرة المُخصصة، وهي مُحاذاة بشكل مناسب لأي نوع يناسب الحجم المطلوب أو أقل. عند حدوث خطأ، تُرجع هذه الدوال NULL وتُعيِّن errno. تُعد محاولة تخصيص أكثر من PTRDIFF_MAX بايت خطأ، لأن كائنًا بهذا الحجم قد يُسبب فائضًا في طرح المؤشرات لاحقًا.
لا تُرجع دالة free() أي قيمة، وتحافظ على errno.
الدالتان realloc() و reallocarray() تُعيدان NULL إذا كان ptr ليس NULL والحجم المطلوب هو صفر؛ لا يُعتبر هذا خطأ. (انظر "سلوك غير محمول" لمشكلات قابلية النقل.) وإلا، قد يكون المؤشر المُعاد هو نفسه ptr إذا لم يُنقل التخصيص (مثلًا، وُجدت مساحة لتوسيع التخصيص في مكانه)، أو مختلفًا عن ptr إذا نُقل التخصيص إلى عنوان جديد. إذا فشلت هذه الدوال، تُترك الكتلة الأصلية دون تغيير؛ لا تُحرر ولا تُنقل.
الأخطاء¶
يمكن أن تفشل دوال calloc() وmalloc() وrealloc() وreallocarray() مع الخطأ التالي:
- ENOMEM
- نفاد الذاكرة. ربما بلغ التطبيق حد RLIMIT_AS أو RLIMIT_DATA الموصوف في getrlimit(2). قد يكون سبب آخر هو أن عدد التعيينات التي أنشأتها عملية المُستدعي تجاوز الحد المُحدد بواسطة /proc/sys/vm/max_map_count.
السمات¶
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
| الواجهة | السمة | القيمة |
| malloc(), free(), calloc(), realloc() | سلامة الخيوط | MT-Safe |
المعايير¶
- malloc()
- free()
- calloc()
- realloc()
- C11, POSIX.1-2008.
- reallocarray()
- لا شيء.
التاريخ¶
- malloc()
- free()
- calloc()
- realloc()
- POSIX.1-2001، C89.
- reallocarray()
- glibc 2.26. OpenBSD 5.6, FreeBSD 11.0.
رفضت malloc() والدوال ذات الصلة الأحجام الأكبر من PTRDIFF_MAX بدءًا من glibc 2.30.
الدالة free() تحافظ على errno ابتداءً من glibc 2.33.
ملاحظات¶
مبدئيًا، يتبع لينكس استراتيجية تفاؤلية لتخصيص الذاكرة. هذا يعني أنه عندما تُرجع malloc() قيمة غير NULL، فلا يوجد ضمان بأن الذاكرة متاحة فعلًا. في حال اتضح أن النظام قد نفدت ذاكرته، فسيُقتل عملية أو أكثر بواسطة قاتل OOM. لمزيد من المعلومات، انظر وصف /proc/sys/vm/overcommit_memory و /proc/sys/vm/oom_adj في proc(5)، وملف مصدر نواة لينكس Documentation/vm/overcommit-accounting.rst.
عادةً، تخصص malloc() الذاكرة من الكومة، وتضبط حجم الكومة حسب الحاجة، باستخدام sbrk(2). عند تخصيص كتل ذاكرة أكبر من MMAP_THRESHOLD بايت، ينفذ تنفيذ glibc لـ malloc() تخصيص الذاكرة كتعيين مجهول خاص باستخدام mmap(2). قيمة MMAP_THRESHOLD هي 128 كيلوبايت مبدئيًا، لكنها قابلة للضبط باستخدام mallopt(3). قبل لينكس 4.7، لم تتأثر التخصيصات المنفذة باستخدام mmap(2) بحد المورد RLIMIT_DATA؛ منذ لينكس 4.7، يُطبّق هذا الحد أيضًا على التخصيصات المنفذة باستخدام mmap(2).
لتجنب الفساد في التطبيقات متعددة الخيوط، تُستخدم كائنات المزامنة (mutexes) داخليًا لحماية هياكل بيانات إدارة الذاكرة التي توظفها هذه الدوال. في تطبيق متعدد الخيوط حيث تخصص الخيوط الذاكرة وتحررها في وقت واحد، قد يحدث تنافس على كائنات المزامنة هذه. للتعامل مع تخصيص الذاكرة بشكل قابل للتوسع في التطبيقات متعددة الخيوط، تنشئ glibc ساحات تخصيص ذاكرة إضافية إذا اكتُشف تنافس على كائن المزامنة. كل ساحة هي منطقة كبيرة من الذاكرة تخصصها النظام داخليًا (باستخدام brk(2) أو mmap(2))، وتُدار بكائنات المزامنة الخاصة بها.
إذا استخدم برنامجك مخصص ذاكرة خاصًا، فيجب أن يفعل ذلك عن طريق استبدال malloc() و free() و calloc() و realloc(). يجب أن تنفذ دوال الاستبدال السلوكيات الموثقة لـ glibc، بما في ذلك معالجة errno، وتخصيصات الحجم صفر، والتحقق من الفائض؛ وإلا، فقد تتعطل أو تعمل بشكل غير صحيح روتينات مكتبة أخرى. على سبيل المثال، إذا لم تحافظ دالة free() البديلة على errno، فقد تفشل روتينات مكتبة تبدو غير ذات صلة دون سبب صحيح في errno. قد تحتاج مخصصات الذاكرة الخاصة أيضًا إلى استبدال دوال glibc أخرى؛ انظر "Replacing malloc" في دليل glibc للتفاصيل.
ترتبط الأعطال في مخصصات الذاكرة دائمًا تقريبًا بفساد الكومة، مثل تجاوز سعة قطعة مخصصة أو تحرير نفس المؤشر مرتين.
تنفيذ malloc() قابل للضبط عبر متغيرات البيئة؛ انظر mallopt(3) للتفاصيل.
سلوك غير محمول¶
سلوك هذه الدوال عندما يكون الحجم المطلوب صفرًا خاص بـ glibc؛ قد تُرجع تطبيقات أخرى NULL دون تعيين errno، ويجب على برامج POSIX المحمولة تحمل مثل هذا السلوك. انظر realloc(3p).
يتطلب POSIX من مخصصات الذاكرة تعيين errno عند الفشل. لكن، لا يتطلب معيار C هذا، ولا ينبغي للتطبيقات المحمولة إلى منصات غير POSIX افتراض ذلك.
لا ينبغي للبرامج المحمولة استخدام مخصصات ذاكرة خاصة، إذ لا يسمح POSIX ومعيار C باستبدال malloc() و free() و calloc() و realloc().
أمثلة¶
#include <err.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MALLOCARRAY(n, type) ((type *) my_mallocarray(n, sizeof(type)))
#define MALLOC(type) MALLOCARRAY(1, type)
static inline void *my_mallocarray(size_t nmemb, size_t size);
int
main(void)
{
char *p;
p = MALLOCARRAY(32, char);
if (p == NULL)
err(EXIT_FAILURE, "malloc");
strlcpy(p, "foo", 32);
puts(p);
}
static inline void *
my_mallocarray(size_t nmemb, size_t size)
{
return reallocarray(NULL, nmemb, size);
}
انظر أيضًا¶
valgrind(1), brk(2), mmap(2), alloca(3), malloc_get_state(3), malloc_info(3), malloc_trim(3), malloc_usable_size(3), mallopt(3), mcheck(3), mtrace(3), posix_memalign(3)
لتفاصيل تنفيذ مكتبة سي لجنو، انظر https://sourceware.org/glibc/wiki/MallocInternals.
ترجمة¶
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>
هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.
إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.
| 2 مايو 2024 | صفحات دليل لينكس 6.9.1 |