被释放的指针未分配,即使它之前已分配
Posted
技术标签:
【中文标题】被释放的指针未分配,即使它之前已分配【英文标题】:Pointer being freed was not allocated even though it was allocated before 【发布时间】:2016-12-10 04:33:29 【问题描述】:我有错误提示 对象 0x7ffbaf002000 错误:未分配指针被释放。但是我已经打印出内存地址,它确实是在 0x7ffbaf002000 之前在循环内的函数allocFlights(Flight**, int)
flight[0] = (Flight*) malloc(sizeof(Flight) * 60)
中分配的。所以我在函数deAllocFlights(Flight**, int)
中打印出std::cout << flight[0] << std::endl
的内存地址,看看它是否存在,它是否存在于循环内的0x7ffbaf002000
我不明白我为什么会遇到这个问题。我还是 C++ 新手。
这是飞行结构:
typedef struct
int flightNum;
char origin[20];
char destination[20];
Plane *plane;
Flight;
void getAllFlights(Flight **flight)
FILE *file = fopen("reservation.txt", "r");
int i = 0, totalFlights;
if(file == NULL)
perror("Error in opening file");
fscanf(file, "%d\n", &totalFlights);
*flight = (Flight*) malloc(sizeof(Flight*) * totalFlights);
allocFlights(flight, totalFlights); // Allocate here
.
.
.
deAllocFlights(flight, totalFlights); // Error: Deallocate here
fclose(file);
函数 allocFlights
void allocFlights(Flight **flight, int totalFlights)
for (int i = 0; i < totalFlights; i++)
flight[i] = (Flight*) malloc(sizeof(Flight) * 60);
std::cout << flight[i] << " " << i << std::endl; // Print out memory address
函数deallocFlights
void deAllocFlights(Flight** flight, int totalFlights)
for (int i = 0; i < totalFlights; i++)
std::cout << flight[i] << " " << i << std::endl; // Print out memory address
free (flight[i]);
主要:
int main()
Flight *flight;
getAllFlights(&flight);
free(flight);
return 0;
【问题讨论】:
选择一个:C 或 C++。这可以为您简化很多事情。 没有像 C/C++ 这样的语言。这是 C++ 请注意,您的代码是 C++,因为您使用std::cout << flight[i] << …
。但是,如果您使用 C++ 编码,则不应使用 malloc()
和 free()
— 如果您必须显式管理内存,则应使用 C++ 的高级 new
和 delete
运算符。跨度>
注意perror()
不会退出,所以如果你打开文件失败,你检查并报告你失败了(好),然后继续使用空文件流,这不会带来幸福。
如果Flight
是非 POD 类型,即使您获得了要编译的代码,这些代码都不起作用。原因是您不能在此类类型上使用malloc
或free
,因为您没有构造对象。放弃这种类型的编码并使用 std::vector
和 C++ 提供的其他容器(并为自己找一本更好的 C++ 书籍/老师/无论你从哪里学习 C++)。
【参考方案1】:
您要取消分配您的第一个航班两次。所以第二次释放它时,系统会告诉你它还没有被分配,因为虽然它被分配了,但它也被释放了。您不需要在最后致电free(flight);
,因为您已经取消了deAllocAllFlights()
中的所有航班。正如 David Schwartz 在 cmets 中提到的那样,这是因为 flight[0]
与 *flight
相同(或者正如他所说的 *(flight + 0)
)。
【讨论】:
这可能有助于提醒他flight[0]
等同于*(flight+0)
,因此等同于*flight
。【参考方案2】:
到处都缺一颗星。
代码将原始变量用作指向Flight
的指针数组(或指向Flight
的指针)。因此必须用双星来定义:
int main()
Flight **flight;
getAllFlights(&flight);
free(flight);
return 0;
每个功能都一样:
void getAllFlights(Flight ***flight)
...
*flight = (Flight**) malloc(sizeof(Flight*) * totalFlights);
void allocFlights(Flight ***flight, int totalFlights)
for (int i = 0; i < totalFlights; i++)
// dereference the pointer first and then access array:
(*flight)[i] = (Flight*) malloc(sizeof(Flight));
void deAllocFlights(Flight*** flight, int totalFlights)
for (int i = 0; i < totalFlights; i++)
std::cout << (*flight)[i] << " " << i << std::endl; // Print out memory address
// dereference the pointer first and then access array
free ((*flight)[i]);
原始代码直接访问指向main
函数中定义的变量的指针,并将其用作数组,这意味着它会转到索引1
的变量后面的地址,甚至更高索引。
另请注意,flights
是变量和所有其他参数的更好名称,因为它实际上是数组。这将使代码更清晰,并有可能更好地避免此类错误。
【讨论】:
我们不知道Flight
是什么。如果是非POD类型,这段代码都不会正常工作。
@PaulMcKenzie :它是 POD,类型在问题中定义。但即使没有,代码也可以正常工作,至少到目前为止呈现的部分 - 内存上只有 malloc 和 free ,无法访问成员(显然未初始化)和类似的东西。
(Flight*) malloc(sizeof(Flight) * 60);
如果Flight
不是 POD 类型,这将不起作用。该代码的明星比好莱坞还多。
@PaulMcKenzie:谢谢你,我错过了这部分(*60
),更新了答案。无论如何,除了结构不会被初始化(包括虚拟表)这一事实之外,它不会真正崩溃,因为稍后它会使用free()
解除分配。我并不是说它的编写方式很好,只是它不会导致崩溃。如果他坚持使用纯 C,那么他真正需要做的就是为结构提供“构造函数”和“析构函数”函数。以上是关于被释放的指针未分配,即使它之前已分配的主要内容,如果未能解决你的问题,请参考以下文章