【问题标题】:Dynamic allocated array is not freed动态分配的数组未释放
【发布时间】:2012-01-08 03:47:54
【问题描述】:

我正在使用上面的代码来动态分配一个数组,在函数内部做一些工作,返回数组的一个元素并释放函数外部的内存。但是当我尝试解除分配数组时,它不会释放内存并且我有内存泄漏。指向 myArray 变量的调试器向我显示错误 CXX0030。为什么?

struct MYSTRUCT
{
    char *myvariable1;
    int myvariable2;
    char *myvariable2;

    ....
};

void MyClass::MyFunction1()
{
    MYSTRUCT *myArray= NULL;

    MYSTRUCT *myElement = this->MyFunction2(myArray);

    ...

    delete [] myArray;
}

MYSTRUCT* MyClass::MyFunction2(MYSTRUCT *array)
{
    array = (MYSTRUCT*)operator new(bytesLength);

    ...

    return array[X];
}

【问题讨论】:

    标签: c++ arrays pointers memory-leaks


    【解决方案1】:

    您应该使用delete[] 的唯一时间是当您使用new[] 进行分配时,但这不是您正在做的事情。您正在使用operator new,这不是您应该用于通用数组分配的。请改用new[]。或者使用向量。

    此外,尽管您将myArray 传递给MyFunction2 作为array,然后在函数内部为array 分配一个新值,但这不会改变调用者中myArray 的值。该变量保留其原始空值,因此您的 delete[] 调用什么也不做。您可以将array 更改为通过引用而不是通过值传递,因此对它的更改将反映在调用者的实际参数中。

    【讨论】:

    • 我会使用更多的 C++ 风格,而 operator new 似乎可以解决问题。此外,运算符 new 是我在本机 C++ 中知道的按大小而不是按元素编号分配数组的唯一方法
    • @Stefano new MYSTRUCT[bytesLength / sizeof(MYSTRUCT)];
    • 你说得对,operator new 是按大小而不是元素编号分配的方式,但你不应该那样做。如果您想要一个 MYSTRUCT 数组,则使用new[] 分配一个 MYSTRUCT 数组。其他任何东西都只是给你一个字节块,而那个字节块是否适合被视为其他东西是实现定义的。
    • @Pubby 有人说你写的代码是向下取整而不是向上取整。此外,除非 bytesLength 是 sizeof(MYSTRUCT) 的倍数,否则缓冲区溢出。
    • @RobKennedy 在 MyFunction2 中我正在使用来自 Microsoft 的函数,该函数将对数组进行一些处理,并将 myArray 作为 MYSTRUCT 列表返回给我。这就是为什么我不能按元素数量分配数组的原因(我不知道其中有多少)。第一次调用 MS 函数时,我会得到 bytesLength
    【解决方案2】:

    你在MyFunction2 中分配了数组,但是你没有返回它的地址。 MyFunction2 的参数是按值传递的,因此在调用它时将myArray 的副本传递给它,但函数本身永远无法更改调用者的局部变量的值。

    对您的问题的简单而明显的答案是将MyFunction2 的参数声明为引用,例如:

    MYSTRUCT* MyClass::MyFunction2(MYSTRUCT*& array)...
    

    然而,更好的解决方案是使用std::vector,而不用担心释放问题。

    【讨论】:

    • 你是个天才 :D 它与 & 一起使用。我尝试使用 std::vector 但使用生成数组元素所需的 Microsoft 函数会得到一些奇怪的行为。例如,数组的第一个元素在位置 0,第二个在位置 3,第三个在位置 7,以此类推。
    • @Stefano 知道这个 Microsoft 功能是什么会很有趣。在我看来,您的结构定义中有错误:std::vector<MyStruct> v(n) 导致的数据结构与MyStruct* v = new MyStruct[n] 完全相同(但数据已初始化,并将自动删除)。
    • 函数是GetAdapterAddresses
    • @Stefano 我在GetAdaptersAddresses 的参数中找不到任何类似的数组(或任何数组);如果我正确理解了函数文档,那么实际上需要的是一些原始内存,函数将在其中构建IP_ADAPTER_ADDRESSES 的链表。我不确定如何用 C++ 最好地表达这一点:我可能只使用vector<unsigned char>reinterpret_cast,但可能是union { unsigned char[n], IP_ADAPTER_ADDRESSES } 的向量。重要的一点是您不能索引到IP_ADAPTER_ADDRESSES 的数组;您必须按照列表中的链接进行操作。
    • @Stefano 是的,但是std::vector<unsigned char> buf( byteCount ) 基本上会做同样的事情,不同的是它会自动释放内存,即使有异常。您可能想要做的只是void* pBuf = &buf[0];,因此您最终会得到void*(并且可以使用static_cast 而不是reinterpret_cast)。如果您无法使其正常工作,请使用实际代码发布问题,即使它有点长。 (在这种情况下,恕我直言,这是有道理的,因为这个函数的接口非常特殊。)
    【解决方案3】:

    您在MyFunction2 内分配数组,但从不释放它。在MyFunction1delete[] 中是空指针,这是一个空操作。我不确定我能不能告诉你应该怎么做,因为你的意图并不明确。

    【讨论】:

    • 我想要做的是得到一个在 MyFunction2 中分配的数组。在此之后,我必须能够对其进行一些工作并将该数组的特定元素返回给 MyFunction1。如果我释放 MyFunction2 中的数组,我将丢失所有内容,而在 Myfunction1 中,我将无法使用返回的元素
    • 您可能希望将指针传递给指针或引用指针,就像 James 建议的那样并使用 new[]
    猜你喜欢
    • 2014-02-23
    • 2019-11-30
    • 2013-07-16
    • 2019-07-08
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 2018-09-01
    相关资源
    最近更新 更多