C - realloc () funktsiyasi - bu ma'lumotni buzadi

Bu oddiy kod bilan nima topganimni qarang:

#include 
#include 
#include 

char *string;

int main(){    

string = (char *) malloc(50*sizeof(char));
strcpy(string, "initi1l wording cont2ining forty-nine ch3r4cters.");
printf("BEFORE: %s\n", string);
string = (char *) realloc(string, 24*sizeof(char));
printf("AFTER: %s\n", string);

system("PAUSE");

return 0;
}

Tashqaridan chiqish:

BEFORE: initi1l wording cont2ining forty-nine ch3r4cters.
AFTER: initi1l wording cont2inia

Yo'lning oxirida "A" ga e'tibor bering! Buning qaerdan kelib chiqqanini, ehtimol, uyma-uyning biror joyida hech qanday tasavvurga ega emasman. Asl ma'lumotlar blokidan emas. Dastlab realloc() ni tuzilmalar dizayni bilan ishlatardim va bu ma'lumotni yanada aniqroq usulda buzgan edi.

Ushbu muammoni qanday hal qilishim mumkin?

3
Ehtimol, hech qanday savol yo'q, lekin javob aniq: realloc buzilmaydi.
qo'shib qo'ydi muallif Per Johansson, manba
Men savol topa olmadim.
qo'shib qo'ydi muallif Mob, manba
Xo'sh, men o'zimning muammoim haqida qanday qilib ishlashim mumkinligini so'rashim mumkin, aixning javobiga javobni ko'ring.
qo'shib qo'ydi muallif Mike mmm, manba

4 javoblar

C strings require a NUL terminator. You're implicitly expecting realloc() to somehow figure out that the memory contains a C string, and replace its last character with NUL. It doesn't do this; you have to do it yourself:

string = (char *) realloc(string, 24*sizeof(char));
string[23] = 0;  //<========= THE FIX
printf("AFTER: %s\n", string);

Boshqacha aytganda, bu sizning kodingizdagi xato.

10
qo'shib qo'ydi
Ha, to'g'ri. Bunga ishora qilganingiz uchun tashakkur, lekin ... Men bir necha tuzilishlarni kichikroq bloklarga qisqartirganimda, oxiridan kelib chiqadigan so'nggi elementlarni kutardim (va NULL sonlantiruvchi belgi bilan ta'minlash shart emas edi). Natijada korruptsiyaning umumiy hajmi bo'ldi.
qo'shib qo'ydi muallif Mike mmm, manba

Yo'q! C "String" da \ 0 bilan ajratilgan belgilar majmui. Bu holda siz "mag'lubiyat" ni chop etishga harakat qilmoqdasiz, shuning uchun tasodifiy \ 0 xotirada topilgunga qadar asl 24 ta belgi va birorta quyruqni olasiz

5
qo'shib qo'ydi
Agar o'lchamni oshirish uchun realloc dan foydalansangiz, eski kontent orqasidagi qism standartda ko'rsatilganidek, noaniq baytlarga ega. Agar siz o'lchamini qisqartirish uchun foydalanayotgan bo'lsangiz, yangi o'lchamdagi xotira sizning dasturingiz uchun faqat tasodifiy xotira joyidir, u har qanday narsani o'z ichiga olishi mumkin, unga kirish huquqi noto'g'ri. Aslida nima bo'ladi (bu holatda, boshqa ilovalar boshqacha yo'l tutishlari mumkin) bu realloc birinchi xotirada bo'sh xotira sifatida belgilash uchun birinchi bir necha baytni yozadi.
qo'shib qo'ydi muallif Daniel Fischer, manba
Ok bolalar. Rahmat. Qaytganim tasodifiy ma'lumotlar tarkibiy tuzilmalarimga qanday qo'shilishini isbotlay oladigan bo'lsam, qaytib kelaman. (Men misolda NULL ni unutganligimga roziman).
qo'shib qo'ydi muallif Mike mmm, manba

C ning qatorlari null tugatilgan. Dasturning qulashi yo'q, men hayratga tushaman.

2
qo'shib qo'ydi
Nima uchun bunday bo'lishi kerak? Ajratilgan blokdan so'ng, masalan, keyingi blokning kattaligi bo'lishi mumkin, agar u qisqa bo'lsa, nol yuqori baytda ;-)
qo'shib qo'ydi muallif Michael Krelin - hacker, manba
Sovuq kuzatuv.
qo'shib qo'ydi muallif Mike mmm, manba

Bu 25 belgidir va sizning dastlabki 24 daqiqada sizda 0 bekor yo'q.

1
qo'shib qo'ydi