ошибка при использовании realloc в C / C ++ - PullRequest
1 голос
/ 14 октября 2011
char *t = malloc(2);
t = "as";

t = realloc(t,sizeof(char)*6);

Я получаю ошибку "неверный указатель: 0x080488d4 *" ..

Я получаю странные ошибки при использовании функций выделения памяти. Есть ли какие-нибудь хорошие инструкции / инструкции, которые могут объяснить мне функции выделения памяти. Я использую Linux ..

Пожалуйста, помогите ..

Ответы [ 5 ]

5 голосов
/ 14 октября 2011

Это ваша проблема:

char *t = malloc(2);
t = "as";

Возможно, вы подумали, что это скопирует двухсимвольную строку "as" в только что выделенный буфер.На самом деле он выбрасывает (утечка) в буфер и меняет указатель , чтобы вместо этого указывать на строковую константу "as", которая хранится впостоянная память рядом с машинным кодом, а не в куче malloc.Поскольку он не в куче, realloc смотрит на указатель и говорит: «Нет, я не могу, это не мое».(Компьютер обходится с вами тем, что выдает вам эту ошибку; когда вы указываете realloc указатель, который не был возвращен malloc или realloc, компьютеру разрешается заставлять демонов вылетать из вашего носа, если онхочет.)

Вот как сделать то, что вы хотели сделать:

char *t = malloc(3);
strcpy(t, "as");

Обратите внимание, что вам нужно место для трех символов, а не двух, из-за неявного терминатора NUL.

Кстати, вам никогда не нужно умножать что-либо на sizeof(char);это 1 по определению .

3 голосов
/ 14 октября 2011

Это не то, как вы назначаете строки в C.

Правильный синтаксис:

char* t = malloc(3);  // Reserve enough space for the null-terminator \0

strncpy(t, "as", 3);
// Copy up to 3 bytes from static string "as" to char* t.
// By specifying a maximum of 3 bytes, prevent buffer-overruns

Выделение 2 байтов недостаточно для "as".
C-строки имеют 1-байтовый нулевой терминатор, поэтому для хранения "as\0".
необходимо по крайней мере 3 байта. (\0 представляет нулевой терминатор)

Код, который вы написали: t = "as"; заставляет указатель t "покинуть" ранее выделенную память и вместо этого указывать на статическую строку "as". Память, выделенная с помощью malloc, «просочилась» и не может быть восстановлена ​​(до тех пор, пока программа не завершится и ОС не восстановит ее).

После этого вы можете позвонить realloc, как вы это сделали изначально. Тем не менее, вы должны не делать t = realloc(t,6);. Если по какой-либо причине произошел сбой realloc, вы потеряли память.

Предпочтительный метод:

new_t = realloc(t, 6);
if (new_t != NULL)  // realloc succeeded
{   t = new_t;  
}
else
{  // Error in reallocating, but at least t still points to good memory!
}
2 голосов
/ 14 октября 2011

Ваш код переназначается t, что делает его точным в другом месте

char *t = malloc(2); //t=0xf00ba12
t = "as"; //t=0xbeefbeef
t = realloc(t,sizeof(char)*6); //confused because t is 0xbeefbeef, not 0xf00b412.

Вместо этого используйте strcpy

char *t = malloc(3); //don't forget about the '\0'
strcpy(t, "as");
t = realloc(t, 6); //now the string has room to breathe
0 голосов
/ 14 октября 2011
char *t = malloc(2);

это означает, что вы создали указатель на область памяти, которая может содержать 2 байта

     +-+-+ 
t -> | | |
     +-+-+ 

, когда вы делаете

t = "as";

, теперь вы указали куда-токроме того, на что он первоначально указывал.теперь он больше не указывает на кучу

t = realloc(t,sizeof(char)*6);

теперь вы берете указатель, указывающий на память только для чтения, и пытаетесь перераспределить его.

при использовании malloc вы выделяете пространство в куче,t в данном случае это указатель на это местоположение, адрес, где находится блок.

Для того, чтобы поместить что-то в это место, вам нужно скопировать туда данные путем разыменования t, это делается записью *перед t:

*t = 'a';   // now 'a' is where t points
*(t+1)='s'; // now 's' is behind a, t still pointing to 'a'

однако в C строка всегда заканчивается 0 (значение ASCII), записанным как '\ 0', поэтому для того, чтобы сделать его строкой, необходимо добавить \0

     +-+-+--+ 
t -> |a|s|\0|
     +-+-+--+ 

, чтобы сделать это, вам нужно вместо этого malloc 3 байта, чем вы можете добавить \ 0, написав *(t+2)='\0';

, теперь t можно рассматривать как указывающий настрока и используется в функциях, которые принимают строки в качестве аргументов, например, strlen( t ) возвращает 2

0 голосов
/ 14 октября 2011

Во-первых, не делайте этого:

char *t = malloc(2);

Сделайте это вместо:

char *t = malloc(2 * sizeof(char));
/* or this: */
char *t = calloc(2, sizeof(char));

Это может показаться не стоящим усилий, но в противном случае вы можете столкнуться с проблемами позжекогда вы работаете с типами больше 1 байта.

В этой строке:

t = "as";

Вы присваиваете адрес строкового литерала "as", поэтому ваш указатель больше не указывает напамять, которую вы выделили.Вам необходимо скопировать содержимое литерала в выделенную память:

char *t = calloc(3, sizeof(char));
/* "ar" is 3 char's: 'a', 'r' and the terminating 0 byte. */
strncpy(t, "ar", 3);
/* then later: */
t = realloc(t,sizeof(char)*6);

Вы также можете просто использовать strdup, что безопаснее:

#include <string.h>

char *t = strdup("ar");
t = realloc(t,sizeof(char)*6);

И не забудьте освободитьпамять

free(t);
...