【问题标题】:C++- freeing dyncamically allocated memory for a member variable of a class gives errorC++-为类的成员变量释放动态分配的内存会出错
【发布时间】:2014-07-16 07:28:39
【问题描述】:

我有这样的课:

Class Attributes
{
Public:
    float* data;
    float* x;
    float min_x;
    float max_x;
    ~Attributes();
};

在主函数的某个点我创建了这个:

Attributes attr;
float* data =(float*)malloc(N*sizeof(float));
float* x =(float*)malloc(N*sizeof(float));
/* populate values of data and x */

attr.data = data;
attr.x = x;

然后我填充这些值并执行我的操作。

现在我明白了,因为我只在堆栈上创建对象,我不需要删除它。 但我认为它只会自动删除成员变量,包括类中的指针,但我必须明确地free 分配给malloc 用于datax 的内存

所以我把类的析构函数写成

Attributes::~Attributes()
{
if(data!=NULL)
    free(data);
if(x!=NULL)
    free(x);
}

正如预期的那样,一旦attr 的范围到期,就会调用析构函数。但在执行free 时出现此错误:

*** Error in '~/Plot':double free or corruption (!prev): 0x0000000002a7e9d0 ***

谁能解释我做错了什么?

【问题讨论】:

  • 你为什么使用mallocfree而不是newdelete
  • @EdChum 我想我可以在 C/C++ 中使用它。我不能吗?
  • BTW free(NULL) 有效,所以测试没用。
  • 你不能,只是不应该:) malloc/free 是 c,new/delete 是 c++。两者在“现代”c++ 中都已被弃用,这意味着有更简单、更安全的方法来执行此操作,例如智能指针:std::unique_ptrstd::shared_ptrstd::weak_ptr
  • 我怀疑你复制了Attributes,而且你不遵守三法则。

标签: c++ class memory-management malloc free


【解决方案1】:

你可能在某处复制attr

这是您问题的一个(工作,不解决其他人在 cmets 中提到的问题)版本。它不会触发任何 doublefree 错误:

#include <cstdlib>

class Attributes
{
public:
    float* data;
    float* x;
    float min_x;
    float max_x;
    ~Attributes() {
      if(data!=NULL)
    free(data);
      if(x!=NULL)
    free(x);
    }
};

int main(int argc, char** argv) {
  int N = 100;
  Attributes attr;
  float* data =(float*)malloc(N*sizeof(float));
  float* x =(float*)malloc(N*sizeof(float));
  attr.data = data;
  attr.x = x;
}

重点是:当你复制 attr 时(甚至是隐式的),你要对任何一个负责

  • 跟踪资源使用情况(两个对象引用相同的内存)
  • 或者也复制分配的资源(即,根据您的特定语义,您可以在(复制)构造函数中将指针设置为 NULL,或者在构造时分配一个新数组(这意味着您需要携带一个长度字段)另外,说真的,你应该使用 std::vector)

您可以使用智能指针库来处理您的具体问题。

【讨论】:

  • 为什么要创建 100 个花车?你为什么不把那个尺寸存储在某个地方?
  • 因为对于内存管理示例来说这并不重要。当然,在实际程序中,它确实很重要;)。
  • 这确实是我无意做的副本,这引起了很多问题。我借了点新东西。非常感谢:)
【解决方案2】:

只需使用std::vector,例如:

class Attributes
{
public:
    void resize(std::size_t size)
    {
       data.resize(size);
       x.resize(x);
    } 
private:
    std::vector<float> data;
    std::vector<float> x;
    float min_x;
    float max_x;
};

【讨论】:

  • 由于 N 似乎是一个编译时常数,std::unique_ptr&lt;std::array&lt;float, N&gt;&gt; 更合适。
  • 如果N 是编译时间常数,float data[N];std::array&lt;float, N&gt; data; 是其他选项。
  • 它们是,但数据最终在自动内存中,而 OP 的目标是使用动态内存(很可能是因为数组可能很大)。
  • @Quentin:所以std::unique_ptr&lt;Attributes&gt; 可以作为补充。顺便说一句,std::vector 超过 std::unique_ptr&lt;std::array&lt;float, N&gt;&gt; 的开销可以忽略不计。
  • 我希望如此。这可能是一个意见问题,但我喜欢在这些情况下使用std::array,因为你几乎不能把它搞砸(没有reserve() 打电话,没有诱人的push_back() 和惊喜重新分配),它没有传达std::vector 所做的“这是一个可增长的容器”的想法。当然,所有这些都可以通过一个瘦包装器来解决,但是嘿,功能已经存在,所以何必麻烦呢。
猜你喜欢
  • 1970-01-01
  • 2013-11-22
  • 2018-07-29
  • 2012-11-01
  • 1970-01-01
  • 2017-06-13
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多