被释放的指针未分配,即使它之前已分配

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 &lt;&lt; flight[i] &lt;&lt; …。但是,如果您使用 C++ 编码,则不应使用 malloc()free() — 如果您必须显式管理内存,则应使用 C++ 的高级 newdelete 运算符。跨度> 注意perror()不会退出,所以如果你打开文件失败,你检查并报告你失败了(好),然后继续使用空文件流,这不会带来幸福。 如果Flight 是非 POD 类型,即使您获得了要编译的代码,这些代码都不起作用。原因是您不能在此类类型上使用mallocfree,因为您没有构造对象。放弃这种类型的编码并使用 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,那么他真正需要做的就是为结构提供“构造函数”和“析构函数”函数。

以上是关于被释放的指针未分配,即使它之前已分配的主要内容,如果未能解决你的问题,请参考以下文章

C: 被释放的 malloc 错误指针未被分配

C 和 C++:释放已分配指针的一部分

C++ - 未分配被释放的指针

Unique_ptr:被释放的指针在放入列表时未分配

这个错误是什么意思? malloc:***对象0x103f000的错误:未分配被释放的指针

未请求分配的内存