重新分配无效指针。中止(核心转储)
Realloc Invalid Pointer. Aborted (core dumped)
*MyFile.h*
typedef char* dado_t;
typedef struct elemento elemento;
typedef struct lista2 lista2;
*MyFile.c*
struct elemento{
dado_t str;
elemento* ant;
elemento* prox;
};
struct lista2{
elemento* primeiro;
elemento* ultimo;
elemento* corrente;
};
void_insert(lista2* l, dado_t d){
elemento* novo = malloc(sizeof(elemento*));
novo->str = malloc(strlen(d) * sizeof(char));
novo->str = d;
l->corrente = novo;
l->primeiro = novo;
l->ultimo = novo;
novo->prox = NULL;
novo->ant = NULL;
}
dado_t replace(lista2* l, dado_t d){
dado_t retorno = malloc(strlen(corrente->str) * sizeof(dado_t));
retorno = corrente->str;
corrente->str = realloc(corrente->str, strlen(d) * sizeof(char));
l->corrente->str = d;
return retorno;
}
为什么会出现此错误?因为 myel->str
是一个用 malloc()
分配的指针。为什么错误?如果 realloc()
发生错误,我正在使用一个临时元素*来阻止
观察:
使用 elemento* novo = malloc(sizeof(elemento*));
时,您 malloc 仅 space 用于指针,但随后将其视为 space 用于结构。这会覆盖堆上的簿记信息。
类型 dado_t
是一个 char *
, 最初 没有指向任何东西(我的意思是,不是 NULL
而是一些随机值) .您在
中正确地为其分配了一些内存
novo->str = malloc(strlen(d) * sizeof(char));
其中有一个小错误:长度为 d
的 C 字符串需要多一个字节的内存用于终止零。所以将其更改为
novo->str = malloc(strlen(d)+1);
这里有两个注意事项:sizeof(char)
保证是 1
(我认为它在规范中;再一次,它没有害处,也许你想确保你有语法在分配 int
s 或其他更大的类型时是正确的)。
其次,大多数标准库都有一个函数可以做到这一点:strdup
。您需要做的就是用您的字符串地址调用它,它会自己完成 +1 部分。
然而,下一行是更严重的错误:
novo->str = d;
在 C 中,您不能 "assign" 一个字符串到另一个字符串。如果您想这样做,您可以将一个字符串的 地址 分配给另一个字符串。这可能会导致无法预料的问题,例如 'assigning' 地址是一个常量字符串(它是有效的但你不能修改它),或者更糟的是,一个在 'local' 上的函数内部创建的字符串堆叠.
在这种情况下,您希望存储函数参数中字符串 d
的完整 副本 ,因此您可以使用
strcpy (novo->str, d);
如果您释放结构 novo
,请不要忘记此指针将为 "lost"。 "lost" 指针是您之前分配的内存块(在字符串 malloc
行中),但不再有指向的有效变量。因此,在释放 elemento
列表时,请先调用 free(xx->str)
。
如果您确保在创建新的 elemento
结构后 str
元素 总是 设置为 NULL
,您可以安全地为字符串调用 free
,即使它可能是 NULL
; free
可以处理。实际上,您似乎总是分配一个值,所以这里不是这种情况,但总的来说,我发现明确清除新创建的结构是安全的,例如 memset (novo, 0, sizeof(elemento));
.
Peter Schneider 正确地指出 elemento* novo = malloc(sizeof(elemento*))
只为指针分配了足够的空间(因为 elemento*
就是这样);在这种情况下,有两种常见的习语,其中任何一种在这里都可以:
elemento* novo = malloc(sizeof(elemento))
elemento* novo = malloc(sizeof(*novo))
当然你也需要听取 Jongware 的建议!
*MyFile.h*
typedef char* dado_t;
typedef struct elemento elemento;
typedef struct lista2 lista2;
*MyFile.c*
struct elemento{
dado_t str;
elemento* ant;
elemento* prox;
};
struct lista2{
elemento* primeiro;
elemento* ultimo;
elemento* corrente;
};
void_insert(lista2* l, dado_t d){
elemento* novo = malloc(sizeof(elemento*));
novo->str = malloc(strlen(d) * sizeof(char));
novo->str = d;
l->corrente = novo;
l->primeiro = novo;
l->ultimo = novo;
novo->prox = NULL;
novo->ant = NULL;
}
dado_t replace(lista2* l, dado_t d){
dado_t retorno = malloc(strlen(corrente->str) * sizeof(dado_t));
retorno = corrente->str;
corrente->str = realloc(corrente->str, strlen(d) * sizeof(char));
l->corrente->str = d;
return retorno;
}
为什么会出现此错误?因为 myel->str
是一个用 malloc()
分配的指针。为什么错误?如果 realloc()
观察:
使用 elemento* novo = malloc(sizeof(elemento*));
时,您 malloc 仅 space 用于指针,但随后将其视为 space 用于结构。这会覆盖堆上的簿记信息。
类型 dado_t
是一个 char *
, 最初 没有指向任何东西(我的意思是,不是 NULL
而是一些随机值) .您在
novo->str = malloc(strlen(d) * sizeof(char));
其中有一个小错误:长度为 d
的 C 字符串需要多一个字节的内存用于终止零。所以将其更改为
novo->str = malloc(strlen(d)+1);
这里有两个注意事项:sizeof(char)
保证是 1
(我认为它在规范中;再一次,它没有害处,也许你想确保你有语法在分配 int
s 或其他更大的类型时是正确的)。
其次,大多数标准库都有一个函数可以做到这一点:strdup
。您需要做的就是用您的字符串地址调用它,它会自己完成 +1 部分。
然而,下一行是更严重的错误:
novo->str = d;
在 C 中,您不能 "assign" 一个字符串到另一个字符串。如果您想这样做,您可以将一个字符串的 地址 分配给另一个字符串。这可能会导致无法预料的问题,例如 'assigning' 地址是一个常量字符串(它是有效的但你不能修改它),或者更糟的是,一个在 'local' 上的函数内部创建的字符串堆叠.
在这种情况下,您希望存储函数参数中字符串 d
的完整 副本 ,因此您可以使用
strcpy (novo->str, d);
如果您释放结构 novo
,请不要忘记此指针将为 "lost"。 "lost" 指针是您之前分配的内存块(在字符串 malloc
行中),但不再有指向的有效变量。因此,在释放 elemento
列表时,请先调用 free(xx->str)
。
如果您确保在创建新的 elemento
结构后 str
元素 总是 设置为 NULL
,您可以安全地为字符串调用 free
,即使它可能是 NULL
; free
可以处理。实际上,您似乎总是分配一个值,所以这里不是这种情况,但总的来说,我发现明确清除新创建的结构是安全的,例如 memset (novo, 0, sizeof(elemento));
.
Peter Schneider 正确地指出 elemento* novo = malloc(sizeof(elemento*))
只为指针分配了足够的空间(因为 elemento*
就是这样);在这种情况下,有两种常见的习语,其中任何一种在这里都可以:
elemento* novo = malloc(sizeof(elemento))
elemento* novo = malloc(sizeof(*novo))
当然你也需要听取 Jongware 的建议!