2014-02-03 3 views
0

Я создаю программу, где структура создается с помощью этого процесса:Проблема освобождения памяти в C с другими функциями

TokenizerT *TKCreate(char *separators, char *ts) { 
    TokenizerT * inu = malloc(sizeof(*inu)); 
    char * sts = malloc(strlen(ts)*sizeof(char)); 
    char * by = malloc(lim*sizeof(char)); 
    strcpy(by, yr); 
    strcpy(sts, ts); 
    inu->sep = by; 
    inu->toks = sts; 
    return inu; 
} 

мне нужно освободить STRUCT ину через другую функцию, но моя функция ниже только кажется чтобы освободить память, связанную с TokenizerT.sep

void TKDestroy(TokenizerT *tk) { 
    free(tk->sep); 
    free(tk->toks); 
} 

Как освободить tk.sep и tk.toks?

EDIT: свободный (т.к) приводит к этой ошибке: «таНос: * ошибка для объекта 0x7fff55662bd8: указатель Освободившись не был выделен * установить контрольную точку в malloc_error_break для отладки»

edit2: определение Struct

struct TokenizerT_ { 
char * sep; 
char * toks; 
}; 

И

void TKDestroy(TokenizerT *tk) { 
    free(tk->sep); 
    free(tk->toks); 
    free(tk); 
} 

приводит к одной и той же ошибки зр ecified в EDIT 1

EDIT 3: Я также добавил мой основной метод:

int main(int argc, char **argv) { 

char * arr = argv[1]; 
char * y = argv[2]; 
TokenizerT jer = *TKCreate(arr, y); 
TKDestroy(&jer); 

return 0; 
} 
+0

Как насчет использования 'free (tk);' after 'free (tk-> sep); бесплатно (tk-> toks); '? – gmorrow

+0

Вы никогда не выделяли tk-> sep или tk-> toks.Начните с этого. Было бы также полезно показать свое определение структуры где-то в сообщении. Может привести к более глубоким ответам. – ryyker

+0

@gmorrow Все еще приводит к ошибке – AbhishekSaha

ответ

1

Прежде всего, таНос из "иной", кажется, не правильно

TokenizerT * inu = malloc(sizeof(inu)); 

Я считаю, что это получить только память 4 байта (в 32-битной системе)

Оно должно быть:

TokenizerT * inu = malloc(sizeof(TokenizerT)); 

И как вы упомянули - "Мне нужно, чтобы освободить STRUCT ина"

Я думаю, что выделено "ина" передается в "TKDestroy (TokenizerT * ки)"

затем:

void TKDestroy(TokenizerT *tk) { 
    free(tk->sep); 
    free(tk->toks); 
    free(tk) // this free is what you want to free "inu" 
+1

Или еще лучше: TokenizerT * inu = malloc (sizeof (* inu)); – tommyo

+1

еще лучше: 'TokenizerT * inu = malloc (sizeof (* inu));' - отметить '*'. Это позволяет изменять тип, не забывая о существенных изменениях. – glglgl

0

Вам просто нужно поменять местами операции, которые вы сделали для выделения:

void TKDestroy(TokenizerT *tk) { 
    free(tk->sep); // for the 3rd malloc() 
    free(tk->toks); // for the 2nd malloc() 
    free(tk);  // for the 1st malloc() 
} 

КСТАТИ: вы знаете, что sizeof(char) является Альва ys 1 - за определение?


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

0

Относительно ваш главный заменить:

TokenizerT jer = *TKCreate(arr, y); 
TKDestroy(&jer); 

С:

TokenizerT *jer = TKCreate(arr, y); 
TKDestroy(jer); 

Причина в том, что ваш создать функция возвращает указатель, который затем перейти на ваш уничтожить-функции ...

0

Причина, по которой ваш код не с этой ошибкой, заключается в том, что &jer является адресом локальной переменной. Это не адрес, возвращенный вызовом malloc.

TokenizerT jer = *TKCreate(arr, y); 
TKDestroy(&jer); 

Таким образом, jer является локальной переменной. Адрес, возвращенный TKCreate, немедленно отменяется, и создается копия структуры. Вы просто не сохраняете адрес, возвращенный TKCreate, и он просочился. Затем, когда вы пытаетесь позвонить бесплатно по адресу &jer, адрес локальной переменной, ваша среда правильно сообщает, что вы переходите на free адрес, который не был создан по вызову malloc.

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

Я хотел бы написать программу, как это:

#include <stdlib.h> 
#include <string.h> 

typedef struct { 
    char *sep; 
    char *toks; 
} TokenizerT; 

TokenizerT TKCreate(const char *seps, const char *toks) 
{ 
    TokenizerT inu; 

    inu.sep = malloc(strlen(seps)+1); 
    strcpy(inu.sep, seps); 

    inu.toks = malloc(strlen(toks)+1); 
    strcpy(inu.toks, toks); 

    return inu; 
} 

void TKDestroy(TokenizerT *tk) 
{ 
    free(tk->sep); 
    free(tk->toks); 
} 

int main(int argc, char **argv) 
{ 
    TokenizerT jer = TKCreate(argv[1], argv[2]); 
    TKDestroy(&jer); 
    return 0; 
} 

Примечания:

  1. По определению, sizeof(char) является 1 так идиома диктует, что он опущен в качестве множителя при обращении к malloc() ,
  2. Я дал параметрам TKCreate те же названия, что и поля struct. Это облегчает понимание того, что происходит. Более того, ваш код выглядел неправильно, поскольку он игнорировал один из параметров.
  3. Как указано выше, struct возвращается значением. Это концептуально проще в обращении.

Вы можете предпочесть, чтобы написать вспомогательную функцию для дублирования строк. Если среда выполнения вашего компилятора уже имеет функцию с именем strdup, вы можете использовать ее. В противном случае вы можете использовать эту тривиальную реализацию:

char *strdup(const char *str) 
{ 
    char *result = malloc(strlen(str)+1); 
    strcpy(result, str); 
    return result; 
} 

Если вы хотите искать нуль-терминатором, как только вы пишете так:

char *strdup(const char *str) 
{ 
    size_t len = strlen(str)+1; 
    char *result = malloc(len); 
    memcpy(result, str, len); 
    return result; 
} 

Тогда код будет выглядеть так:

#include <stdlib.h> 
#include <string.h> 

char *strdup(const char *str) 
{ 
    size_t len = strlen(str)+1; 
    char *result = malloc(len); 
    memcpy(result, str, len); 
    return result; 
} 

typedef struct { 
    char *sep; 
    char *toks; 
} TokenizerT; 

TokenizerT TKCreate(const char *seps, const char *toks) 
{ 
    TokenizerT inu; 
    inu.sep = strdup(seps); 
    inu.toks = strdup(toks); 
    return inu; 
} 

void TKDestroy(TokenizerT *tk) 
{ 
    free(tk->sep); 
    free(tk->toks); 
} 

int main(int argc, char **argv) 
{ 
    TokenizerT jer = TKCreate(argv[1], argv[2]); 
    TKDestroy(&jer); 
    return 0; 
} 

Если вы отчаянно хотите вернуть указатель на структуру, выполните следующие действия:

#include <stdlib.h> 
#include <string.h> 

char *strdup(const char *str) 
{ 
    size_t len = strlen(str)+1; 
    char *result = malloc(len); 
    memcpy(result, str, len); 
    return result; 
} 

typedef struct { 
    char *sep; 
    char *toks; 
} TokenizerT; 

TokenizerT *TKCreate(const char *seps, const char *toks) 
{ 
    TokenizerT *inu = malloc(sizeof *inu); 
    inu->sep = strdup(seps); 
    inu->toks = strdup(toks); 
    return inu; 
} 

void TKDestroy(TokenizerT *tk) 
{ 
    free(tk->sep); 
    free(tk->toks); 
    free(tk); 
} 

int main(int argc, char **argv) 
{ 
    TokenizerT *jer = TKCreate(argv[1], argv[2]); 
    TKDestroy(jer); 
    return 0; 
} 

Обратите внимание, в частности, на то, что я называю TKCreate и TKDestroy.

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

Смежные вопросы