Причина, по которой ваш код не с этой ошибкой, заключается в том, что &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;
}
Примечания:
- По определению,
sizeof(char)
является 1
так идиома диктует, что он опущен в качестве множителя при обращении к malloc()
,
- Я дал параметрам
TKCreate
те же названия, что и поля struct
. Это облегчает понимание того, что происходит. Более того, ваш код выглядел неправильно, поскольку он игнорировал один из параметров.
- Как указано выше,
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()
. В реальном коде производства вы бы этого не сделали, но для ясности изложения гораздо лучше опустить его здесь.
Как насчет использования 'free (tk);' after 'free (tk-> sep); бесплатно (tk-> toks); '? – gmorrow
Вы никогда не выделяли tk-> sep или tk-> toks.Начните с этого. Было бы также полезно показать свое определение структуры где-то в сообщении. Может привести к более глубоким ответам. – ryyker
@gmorrow Все еще приводит к ошибке – AbhishekSaha