free():释放 2d 指针时指针无效
free(): invalid pointer when freeing a 2d pointer
我有一个二维指针数组:
char **fields = calloc(1, sizeof(char *));
我给它添加了不同的字符串,像这样:
if(i > 0) fields = realloc(fields, (i+1) * sizeof(char *));
fields[i] = calloc(size, sizeof(char));
然后我使用 memcpy
进入 fields[i]
所需的字符串。
程序结束时,当我尝试释放字段时,我是这样做的:
int j=0
while(fields != NULL && fields[j]){
free(fields[j]);
j++;
}
free(fields);
程序将 4 个字符串插入到字段中。
第一个字符串按预期释放,但是在循环的第二次迭代 (j=1) 中,程序停止并输出错误:free(): invalid pointer
编辑:我制作了一个具有相同问题的短程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char **fields = calloc(1, sizeof(char *));
int fieldsIndex = 0,i=0;
while (i<4) {
if(fieldsIndex > 0){
fields = realloc(fields, (fieldsIndex + 1) * sizeof(char *));
fields[fieldsIndex] =NULL;
printf("amount of field places: %d\n", (fieldsIndex + 1));
}
fields[fieldsIndex] = calloc(8, sizeof(char));
fields[fieldsIndex] = "88888888";
fieldsIndex++;
i++;
}
int j=0;
for(j=0; j<i; j++){
printf("field: %s\n", fields[j]);
free(fields[j]);
}
free(fields);
return 0;
}
有人能帮忙吗?
主要解决 MRE。
主要问题出在这一行:
fields[fieldsIndex] = "88888888";
不正确的原因有两个:
首先你需要在数组中多一个元素作为空字节。
其次,你让fields[fieldsIndex]
指针指向字符串文字,这不仅会导致内存泄漏,而且这些字符串文字通常存储在内存的只读部分,要么释放指向字符串文字的指针的行为未定义。
您需要将字符串复制到刚刚分配的内存中。只要您保留足够的内存,使用 memcpy
应该可以工作,如前一点所述,更简洁的方法是使用 strdup
.
另一个问题是 if(fieldsIndex > 0)
因为那时 fields[0]
不会分配内存。
一些其他注意事项,如果您知道字符串的数量 (i < 4
),则不需要 realloc
,只需为第一个 [中的所有指针分配 space =20=]*(假设不是构建MRE带来的),另外i
和fieldsIndex
似乎是多余的。
Here is a demo 保持 realloc
(因为它与 OP 相切):
int main()
{
char **fields = NULL;
char **tempfields; // I advise the use of an auxiliary pointer for reallocation
int fieldsIndex = 0;
while (fieldsIndex < 4)
{
tempfields = realloc(fields, (fieldsIndex + 1) * sizeof *fields); //*
if (!tempfields)
{
// handle the allocation error appropriately
}
fields = tempfields;
printf("amount of field places: %d\n", (fieldsIndex + 1));
fields[fieldsIndex] = strdup("88888888");
// Or
// fields[fieldsIndex] = calloc(9, sizeof **fields); // check return
// strcpy(fields[fieldsIndex], "88888888");
fieldsIndex++;
}
// With int iterator
int j = 0;
for (j = 0; j < fieldsIndex; j++)
{
printf("field: %s\n", fields[j]);
free(fields[j]);
}
free(fields);
}
或者在 fields
中使用标记元素:
// With sentinel
tempfields = realloc(fields, (fieldsIndex + 1) * sizeof *fields);
if (!tempfields)
{
// handle the allocation error appropriately
}
fields = tempfields;
fields[fieldsIndex] = NULL;
while (*fields)
{
printf("field: %s\n", *fields);
free(*fields);
fields++;
}
free(tempfields);
我有一个二维指针数组:
char **fields = calloc(1, sizeof(char *));
我给它添加了不同的字符串,像这样:
if(i > 0) fields = realloc(fields, (i+1) * sizeof(char *));
fields[i] = calloc(size, sizeof(char));
然后我使用 memcpy
进入 fields[i]
所需的字符串。
程序结束时,当我尝试释放字段时,我是这样做的:
int j=0
while(fields != NULL && fields[j]){
free(fields[j]);
j++;
}
free(fields);
程序将 4 个字符串插入到字段中。
第一个字符串按预期释放,但是在循环的第二次迭代 (j=1) 中,程序停止并输出错误:free(): invalid pointer
编辑:我制作了一个具有相同问题的短程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
char **fields = calloc(1, sizeof(char *));
int fieldsIndex = 0,i=0;
while (i<4) {
if(fieldsIndex > 0){
fields = realloc(fields, (fieldsIndex + 1) * sizeof(char *));
fields[fieldsIndex] =NULL;
printf("amount of field places: %d\n", (fieldsIndex + 1));
}
fields[fieldsIndex] = calloc(8, sizeof(char));
fields[fieldsIndex] = "88888888";
fieldsIndex++;
i++;
}
int j=0;
for(j=0; j<i; j++){
printf("field: %s\n", fields[j]);
free(fields[j]);
}
free(fields);
return 0;
}
有人能帮忙吗?
主要解决 MRE。
主要问题出在这一行:
fields[fieldsIndex] = "88888888";
不正确的原因有两个:
首先你需要在数组中多一个元素作为空字节。
其次,你让
fields[fieldsIndex]
指针指向字符串文字,这不仅会导致内存泄漏,而且这些字符串文字通常存储在内存的只读部分,要么释放指向字符串文字的指针的行为未定义。您需要将字符串复制到刚刚分配的内存中。只要您保留足够的内存,使用
memcpy
应该可以工作,如前一点所述,更简洁的方法是使用strdup
.
另一个问题是
if(fieldsIndex > 0)
因为那时fields[0]
不会分配内存。
一些其他注意事项,如果您知道字符串的数量 (i < 4
),则不需要 realloc
,只需为第一个 [中的所有指针分配 space =20=]*(假设不是构建MRE带来的),另外i
和fieldsIndex
似乎是多余的。
Here is a demo 保持 realloc
(因为它与 OP 相切):
int main()
{
char **fields = NULL;
char **tempfields; // I advise the use of an auxiliary pointer for reallocation
int fieldsIndex = 0;
while (fieldsIndex < 4)
{
tempfields = realloc(fields, (fieldsIndex + 1) * sizeof *fields); //*
if (!tempfields)
{
// handle the allocation error appropriately
}
fields = tempfields;
printf("amount of field places: %d\n", (fieldsIndex + 1));
fields[fieldsIndex] = strdup("88888888");
// Or
// fields[fieldsIndex] = calloc(9, sizeof **fields); // check return
// strcpy(fields[fieldsIndex], "88888888");
fieldsIndex++;
}
// With int iterator
int j = 0;
for (j = 0; j < fieldsIndex; j++)
{
printf("field: %s\n", fields[j]);
free(fields[j]);
}
free(fields);
}
或者在 fields
中使用标记元素:
// With sentinel
tempfields = realloc(fields, (fieldsIndex + 1) * sizeof *fields);
if (!tempfields)
{
// handle the allocation error appropriately
}
fields = tempfields;
fields[fieldsIndex] = NULL;
while (*fields)
{
printf("field: %s\n", *fields);
free(*fields);
fields++;
}
free(tempfields);