عرض strcpy والسلسلة في الذاكرة
-
26-12-2019 - |
سؤال
لدي برنامج مثل هذا (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.كنت تستخدم خطأ محدد التنسيق لطباعة العنوان.
النتيجة سواء كان متوقعا أو غير متوقع.