لماذا malloc تخصيص عدد مختلف من بايت من طلبتها ؟

StackOverflow https://stackoverflow.com/questions/430163

  •  08-07-2019
  •  | 
  •  

سؤال

لدي قطعة من التعليمات البرمجية

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int main(){
    void *a, *b;

    a = malloc(16);
    b = malloc(16);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);

    a = malloc(1024);
    b = malloc(1024);
    printf("\n   block size (for a): %p-%p : %li", b, a, b-a);  
}

لا يجب طباعة هذه الأخيرة تخصيص حجم الكتلة (16 أو 1024)?بدلا يطبع 24 و 1032 ، لذلك مقدار الذاكرة المخصصة يبدو 8 بايت إضافية.

مشكلتي هي (قبل إجراء هذا الاختبار الحالة) أن أفعل malloc() في وظيفة (1024 بايت) ، وإعادة تخصيص النتيجة.عند التحقق من حجم الكتلة على وظيفة عودة أحصل على 516 كتل...وأنا لا أفهم لماذا.أعتقد أن هذا قد يكون سبب تلف الذاكرة الذي يحدث بعد القيام ببعض المعالجة على تخصيص المخازن المؤقتة:)

تحرير: رأيت كيف يمكنني الحصول على حجم مجموعة من مؤشر في C ؟ و يبدو أن نسأل نفس الشيء ، آسف على إعادة نشر.

لقد إعادة بنائه بلدي على سبيل المثال إلى قانون أكثر تحديدا:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

short int * mallocStuff(long int number, short int base){
    short int *array;
    int size=1024;

    array=(short int*)calloc(1,size);
    //array=(short int*)malloc(size);

    return array;
}

int main(){
    short int **translatedArray;

    translatedArray=malloc(4*sizeof(short int));

    int i;
    for(i=0;i<4;i++){
        translatedArray[i]=mallocStuff(0,0);

        if(i>0)
            printf("\n   block size (for a): %p-%p : %i",
                translatedArray[i], translatedArray[i-1], translatedArray[i]-translatedArray[i-1]);
    }

    return 0;
}

و الناتج هو

   block size (for a): 0x804a420-0x804a018 : 516
   block size (for a): 0x804a828-0x804a420 : 516
   block size (for a): 0x804ac30-0x804a828 : 516

وفقا لما سبق بعد ذلك أكبر من 1024.هل أنا مخطئ ؟

هل كانت مفيدة؟

المحلول

لديك علة.بدلا من:

translatedArray=malloc(4*sizeof(short int));

يجب أن يكون لديك

translatedArray=malloc(4*sizeof(short int*));

ملاحظة المفقودين المؤشر في التعليمات البرمجية الخاصة بك.وأظن أن هذا هو حيث لوحظ سلوك ينبع من.


تلاحظ أيضا أن 0x804a420 - 0x804a018 = 1032, لا 516.الصيغة translatedArray[i] - translatedArray[i - 1] يعطيك عدد عناصر (قصيرة رجات ، أو ببساطة أكثر, شورت) في بين اثنين من عناوين لا عدد بايت.

نصائح أخرى

أولا، Malloc لا تقدم أي ضمانات بأن مكالمتين malloc المتعاقبة تعود المؤشرات المتعاقبة.

والثانية، اعتمادا على بنية محددة، تطبق قواعد محاذاة مختلفة. في بعض الأحيان قد تسأل عن بايت واحد، ولكن العمارة يفضل المخصصات على فترات 8- أو 4 بايت.

وثالثا، malloc يحتاج إلى بعض النفقات العامة لتخزين كم كبير من كتلة المخصصة هو، وما إلى ذلك.

لا تجعل افتراضات حول ما تقوم به malloc الماضي ما تقول وثائق!

وظيفة malloc دائما يخصص أكثر قليلا مما كنت أطلب، من أجل تخزين بعض المعلومات مسك الدفاتر. بعد كل شيء، عند استدعاء free() أنه يحتاج إلى معرفة كيف كبيرة كتلة.

وبالإضافة إلى ذلك، عموما تطبيقات malloc سوف تقريب الحجم المطلوب حتى متعددة المقبل من 8 أو 16 أو بعض الدول الأخرى عدد جولة العش.

على تحديث : في الجواب الحقيقي على سؤالك يكمن في استخدامك للنوع short int. عندما تفعل الحساب مؤشر (الطرح) بين مؤشرات مطبوعة، C و C ++ العودة الفرق في رقم من الأشياء أشارت إلى. منذ كنت لافتا إلى short int، وهو اثنين بايت في الحجم، والقيمة التي تم إرجاعها نصف ما كنت تتوقع.

وعلى صعيد آخر، malloc يخصص دائما عدد معين من بايت ، بغض النظر عن ما يلقي نتيجة لبعد ذلك. جرب هذا:

    array=(short int*)malloc(sizeof(short int) * size);

ولا توجد ضمانات بأن اثنين من المكالمات malloc العودة كتل معبأة تماما معا - في واقع الأمر ليست هناك أية ضمانات عن نتيجة على الإطلاق، إلا أنه لو كان غير NULL سوف نشير إلى كتلة كأقل كبير مثل واحد المطلوب.

وعلى الصعيد الداخلي، فإن معظم mallocs بيانات عقد العمل لمساعدتهم على إدارة الكومة. على سبيل المثال، قد تتضمن تلك بايت 8 اثنين من المؤشرات - لافتا إلى كتلة التالي، ويشير إلى كتلة السابق. أنا لا أعرف ما هي تلك بايت 8 لأنك لم تذكر نظام التشغيل الذي تقوم بتشغيله، ولكن من الطبيعي تماما لmalloc لاستخدام بعض الذاكرة لنفسها وراء الكواليس.

وبعض موزعي (على سبيل المثال على ويندوز) توفر وظيفة مكتبة لاكتشاف حجم كتلة إعطاء مؤشر، ومع ذلك، والبعض لا، كما انها سمة من سمات مقصور على فئة معينة إلى حد ما.

وماذا تعتمد عوائد malloc على تنفيذ malloc، والهندسة المعمارية. وكما قال آخرون بالفعل، ويضمن لك الحصول على ما لا يقل عن المبلغ المطلوب من الذاكرة، أو NULL. وهذا هو أيضا السبب في بعض الأحيان، يمكن أن تكتب بعد نهاية صفيف، وليس الحصول على خطأ تجزئة. انها لأنك فعلا وصول صالح إلى هذه الذاكرة، أنت فقط لا يعرفون ذلك.

وعادة ما يتم تنفيذ malloc () عن طريق تقسيم كومة المتاحة في قطع من مختلف الأحجام. في قضيتك، malloc () إرجاع 2 متتالية 1024 (أو 16) قطع بايت. يتم استخدام مساحة 8 بايت أذكر لكم من قبل malloc () لالمحاسبة من المعلومات.

وانظر malloc دوغ ليا و() الملاحظات impl هنا لفهم ما يجري في وراء الكواليس: <لأ href = "http://g.oswego.edu/dl/html/malloc.html" يختلط = "نوفولو noreferrer "> http://g.oswego.edu/dl/html/malloc.html

وmalloc() سيكون لها انها النفقات العامة الخاصة.

وناهيك عن أن هناك ما يضمن أن 2 مخصصات متتالية سيكون بجانب بعضها البعض لتبدأ.

إذا malloc يعود أي شيء آخر غير لاغية، ثم الذاكرة التي تم تخصيص <م> للبرنامج ديها الحجم الذي تم تمريره إلى malloc. أخذ الفرق المؤشر بين القيم عودة اثنين من الفرق يدعو إلى malloc يمكن أن يكون لها اي قيمة وليس له علاقة (القليل أيضا) للقيام مع حجم كتلة من كتلة المخصصة الأول.

ولقد وجدت this..and الاختيار على الرابط أدناه لمزيد من المعلومات.

تخصيص

ويتم تخصيص كتلة من تجمع المجاني عن طريق تحويل أولا بايت طلب فهرس في مجموعة دلو، وذلك باستخدام المعادلة التالية:

وهناك حاجة = طلب + 8

وإذا لزم الأمر <= 16، ثم دلو = 0

وإذا لزم الأمر> 16، ثم دلو = (سجل (الحاجة) / السجل (2) تقريب لأسفل إلى أقرب عدد صحيح) - 3

وحجم كل كتلة في القائمة الراسية التي كتبها دلو كتلة وحجم = 2 دلو + 4. إذا كانت قائمة في دلو فارغ، يتم تخصيص الذاكرة باستخدام روتين sbrk لإضافة لبنات إلى القائمة. إذا كان حجم كتلة أقل من الصفحة، ثم يتم تخصيص الصفحة باستخدام روتين sbrk، ووصل عدد من الكتل في بقسمة حجم الكتلة في حجم الصفحة تمت إضافتها إلى القائمة. إذا كان حجم كتلة مساوية أو أكبر من صفحة، يتم تخصيص الذاكرة المطلوبة باستخدام روتين sbrk، ويضاف كتلة واحدة إلى قائمة حرة للدلو. إذا كانت القائمة الحرة ليست فارغة، يتم إرجاع كتلة على رأس القائمة إلى المتصل. كتلة التالي على القائمة ثم يصبح الرئيس الجديد.

<وأ href = "http://publib.boulder.ibm.com/infocenter/systems/index.jsp؟topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm" يختلط = " noreferrer نوفولو "> http://publib.boulder.ibm.com/infocenter/systems/index.jsp؟topic=/com.ibm.aix.genprogc/doc/genprogc/sys_mem_alloc.htm

وقبل المؤشر يقف حجم المصفوفة التالية، وهو عدد صحيح 32/64 بت (لا أعلم إذا وقعت أو غير الموقعة)

لذلك يبدو أن مقدار الذاكرة المخصصة ل8 بايت إضافية؟ التنفيذ malloc() على النظام الخاص بك يبدو أن تخصيص بايت إضافية للحفاظ على معلومات البيانات الفوقية مثل كيفية كبيرة قسم كومة هو، ما هو عنوان البداية وما إلى ذلك من المعلومات.

وعلى الرغم من أن يختلف على منصات مختلفة. على أنظمة X86 بلدي، malloc() تخصيص دقيقة من وحدات البايت 17، حتى لو كنت أنا طالبا malloc(0).

int main(void) {
    int *p = malloc(0);
    if(p == NULL) {
        /* error handling */
    }
    printf("%d\n",p[-1]);/ *it prints 17 bytes */
    /* some code */
    return 0;
}

وmalloc () قد تخصيص الذاكرة القريبة، ولكن عندما malloc دعوتكم () 2 مرات ولا يمكن أن نتوقع تخصيص الذاكرة لتكون متجاورة بطرح اثنين من المؤشرات variabls ...

الذاكرة

ولكن المخصصة هي الذاكرة الظاهرية التي هي جزء من تنفيذ النواة، إدارة الذاكرة (VFS) لتكون محددة. قد لا يؤثر على الأداء الوظيفي التطبيق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top