C - пераразмеркаваць () функцыя - доказ разбэшчвае дадзеныя

Паглядзіце, што я знайшоў з дапамогай гэтага простага кода:

#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;
}

Outpout з'яўляецца:

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

Звярніце ўвагу на гэта «а» ў канцы радка! Я паняцця не маю, дзе гэта адбываецца з, можа быць, дзесьці ў кучы. Гэта не з зыходнага блока дадзеных. Першапачаткова я выкарыстаў пераразмеркаваць() з масівамі структур, і гэта было відавочна, разбэшчвае дадзеныя ў больш істотным чынам.

Як я магу вырашыць гэтую праблему?

3
Ну, можа быць, няма ніякага пытання, але адказ відавочны: пераразмеркаваць не парушаная.
дададзена аўтар Per Johansson, крыніца
Я не мог знайсці пытанне.
дададзена аўтар Mob, крыніца
Ну, я мог бы спытаць адзін пазней пра тое, як я магу працаваць вакол маёй праблемы, убачыць мой адказ на адказ Aix ст.
дададзена аўтар Mike mmm, крыніца

4 адказы

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);

Іншымі словамі, гэта памылка ў кодзе.

10
дададзена
Так, дакладна. Дзякуй за ўказанне, што, але ... Калі я дрыжалі масіў структур меншага блока я чакаў апошнія элементы, каб прыйсці ў рэшце рэшт (і не павінна паставіць завяршальны сімвал NULL). Тое, што адбылося татальная карупцыя.
дададзена аўтар Mike mmm, крыніца

Гэта не значыць! У C "String" ўяўляе сабой набор сімвала <моцнага> падзеленага \ 0 . У гэтым выпадку пры спробе надрукаваць «радок», таму вы атрымаеце вашыя арыгінальныя 24 сімвалаў і некаторы хвост, пакуль выпадковы \ 0 не знойдзены ў памяці

5
дададзена
Калі вы выкарыстоўваеце пераразмеркаваць, каб павялічыць памер, частка за старым змесцівам ўтрымлівае нявызначаныя байт, як паказана ў стандарце. Калі вы выкарыстоўваеце яго, каб паменшыць памер, памяць за новы памер проста любое выпадковае месца ў памяці для вашай праграмы, яна можа ўтрымліваць што-небудзь, доступ да яе з'яўляецца несапраўдным. Што на самой справе адбываецца (у дадзеным выпадку, іншыя варыянты ажыццяўлення могуць паводзіць сябе па-рознаму), што пераразмеркаваць перазапісваліся першыя некалькі байт, каб адзначыць яго ў якасці вольнай памяці.
дададзена аўтар Daniel Fischer, крыніца
Ухваленыя ванты. Дзякуючы. Я вярнуся, калі я магу даказаць, як пераразмеркаваць з'яўляецца даданне выпадковых дадзеных у мой масіў структур. (Я згодны я забыўся NULL у прыкладзе радкі).
дададзена аўтар Mike mmm, крыніца

Радкі ў C з'яўляюцца нулём. Я здзіўлены, што праграма не ўрэзацца.

2
дададзена
Чаму б гэта? Пасля таго, як выдзелены блок можа быць, напрыклад, памер наступнага блока, які, калі гэта коратка мае нулявыя старэйшыя байты ;-)
дададзена аўтар Michael Krelin - hacker, крыніца
Крута назіранне.
дададзена аўтар Mike mmm, крыніца

Гэта сімвал 25 і ў вас няма 0-тэрмінатараў першых 24.

1
дададзена