سؤال

لدي برنامج مثل هذا (x86_64 GNU/Linux)

int main()
{
    char s[] = "123456789";
    char d[] = "123";
    strcpy(d, s);

    printf("%p, %0p\n", s, d);
    printf("%s, %s", s, d);

    return 0;
}

والإخراج هو :0xEB6D2930 0xEB6D2910 123456789 123456789 أنا مرتبك قليلاً مع النتيجة التي أعتقد أن البرنامج في الذاكرة مثل هذا:

  • '9','\0' . .
  • '5','6','7','8'
  • 0x7fff813af310:'1'،'2'،'3'،'4'
  • 0x7fff813af300:'1'،'2'،'3'،'\0'

لذلك يجب أن تكون النتيجة *s = "789"، *d = "123456789"

هل يمكن أن تشرحوا يا رفاق لماذا النتيجة ليست كما اعتقدت؟لقد قمت بتغيير محدد التنسيق إلى ٪ p لطباعة عنوان D و S أعرف أن S و D متداخلين ، لذا لا يوجد مساحة كافية لـ D لعقد S والتي قد تؤدي إلى سلوك غير محدد ، لكن على أي حال كنت أتساءل عن سبب النتيجة هو *s = "123456789" *d = "123456789"

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

المحلول

من الإخراج تظهر تخطيط العنوان ويبدو أن محتواه الأولي هو:

       offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  
d: 0xeb6d2910 30 31 32 00 xx xx xx xx xx xx xx xx xx xx xx xx | 1 2 3 . . . . . . . . . . . . .
   0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . . 

بعد strcpy(d, s):

       offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  
d: 0xeb6d2910 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . . 
   0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . . 

ومع ذلك، أما بالنسبة d تم تخصيص ذاكرة أقل كما تم استخدامها أثناء strcpy() يستدعي الكود سلوكًا غير محدد.

نصائح أخرى

يحتوي برنامجك على سلوك غير محدد في هاتين النقطتين:

  • تجاوز سعة المخزن المؤقت مع strcpy():لا تكتب في ذاكرة لا تملكها.
  • محدد تنسيق خاطئ لـ printf():يستخدم %p لطباعة عناوين المؤشر.يعمل فقط مع مؤشرات البيانات بالرغم من ذلك.

الرجاء استخدام النموذج المناسب ل main, ، لقد أوشكت على الحصول عليها (قد يكون هذا هو UB، على الرغم من أنني لم أتبع كل الحجج):

int main(void)
int main(int argc, char* argv[])

أو أن الامتدادات المتوافقة أو المحددة للتنفيذ صالحة.

السلوك غير المحدد يعني أن كل شيء يسير، حتى شياطين الأنف.

البرنامج تحتج السلوك غير معرف لأن:
1. d لا يكون لديك مساحة كافية لعقد سلسلة أكبر من 4 بايت (بما في ذلك \0).
2.كنت تستخدم خطأ محدد التنسيق لطباعة العنوان.

النتيجة سواء كان متوقعا أو غير متوقع.

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