如何释放重新分配的内存?C++

8

我试图释放已经重新分配的内存,但是我得到了一个错误...

float * foo = NULL;
float * bar = NULL;

void update()
{
    ...
    foo = (float *)malloc( a * 2 * sizeof(float));
    ...
    bar = (float *)realloc( foo, a * 2 * sizeof(float));
    ...
    free( foo );
    ...
    // when i do
    if(bar != NULL)
    {
        free(bar); // <-- error at executing
    }
}

我遇到了错误:http://d.pr/mpBF,Visual Studio显示以下文件:
osfinfo.c
=========
void __cdecl _unlock_fhandle (
        int fh
        )
{
        LeaveCriticalSection( &(_pioinfo(fh)->lock) );
}

有什么想法吗?

1
a变量的值是否为0? - Juho
1
在那些malloc和realloc之间,你是否对foo做了任何操作?或者在realloc和free之间,你是否对bar做了任何操作? - Juho
3
很有趣...这段代码在我的GCC上运行良好...我认为你的问题实际上是在其中一个“...”部分引起的... - André Puel
2
这不是你问题的原因,但请允许我说if(bar != NULL)有点无用,因为free在给定空指针时不执行任何操作。 - Damon
@TalPressman,是的,我更新了代码,你可以看到它了。@Juho,实际上这段代码不完全是我的,我正在调试,因为我遇到了内存泄漏 T_T。@André Puel,感谢您的测试。 - JohnnyAce
1
@aljndrrr bames53发布的解决方案是错误的。如果调用realloc失败,它将返回NULL,并且您将无法释放先前由malloc调用分配的内存。David Heffernan的答案展示了正确处理mallocrealloc的方法。 - Praetorian
4个回答

6
foo = (float *)malloc( a * 2 * sizeof(float));
bar = (float *)realloc( foo, a * 2 * sizeof(float));
free( foo ); // oops, foo has gone

在调用free(foo)的时候,foo已经失效了,因为当你调用realloc时,它已经被释放了。代码应该像这样的伪代码:
foo = (float *)malloc( a * 2 * sizeof(float));
if (foo == NULL) 
    return ERROR_CODE;
...
bar = (float *)realloc( foo, a * 2 * sizeof(float));
if (bar == NULL) 
{
    free(foo);
    return ERROR_CODE;
}
...
free(bar);
return SUCCESS;

当然,由于这是C++语言,你应该避免使用mallocfree,转而使用std::vector<float>

2
当您重新分配内存时,不应该释放旧的内存。
bar = (float *)realloc( foo, a * 2 * sizeof(float));
free( foo ); // <-- this is wrong

您需要:

float * foo = NULL;

void update()
{
    ...
    foo = (float *)malloc( a * 2 * sizeof(float));
    ...
    float * bar = (float *)realloc( foo, a * 2 * sizeof(float));
    if(bar)
       foo = bar;
    ...
    free(foo);
}

1
这段代码存在经典的 realloc 错误。如果调用 realloc 失败,那么你将无法释放 foo,从而导致内存泄漏。 - David Heffernan
当然,在free之前不必检查NULL(但是在mallocrealloc之后必须检查)。 - James Kanze
@DavidHeffernan 已修复。(不过在分配错误的情况下,我仍然将其留给“...”来决定应该发生什么) - bames53
@bmaes53 很好。我已经取消了我的踩票,并且在调用 free 之前也删除了多余的 if foo != NULL 检查。 - David Heffernan

2
我的猜测是realloc调用成功扩展了由malloc调用分配的内存。在这种情况下,foobar都将指向相同的内存地址,您在尝试释放bar之前某个地方释放了foo,导致重复删除。
您根本不需要释放foo,因为如果在重新分配期间移动了内存区域,则realloc会为您执行此操作。来自链接页面的内容如下:

如果指向的区域已被移动,则进行free(ptr)。


1

一旦您将指针传递给realloc(),它就被正式释放(释放),您不得再次释放它。

C99 §7.20.3.4 realloc函数

2 realloc函数释放由ptr指向的旧对象,并返回一个指向具有size指定大小的新对象的指针。新对象的内容应与解除分配之前的旧对象相同,最多为新旧大小中较小的那个。新对象中超出旧对象大小的任何字节都具有不确定的值。

realloc()可能会返回与给定指针相同的指针,但通常不能假设它会这样做。一旦您将指针传递给realloc()(或free()),您必须假定它不再是有效指针。

C++中的规则基本相同;它包含了C89标准中的来自C的函数,例如realloc()

您的系统正确地抱怨您正在释放未分配的内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接