【问题标题】:"pointer being freed was not allocated"“未分配被释放的指针”
【发布时间】:2014-01-28 11:17:40
【问题描述】:
#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
#include <sstream>

using namespace std;

class CFile {
public:
    CFile(string filename); 
    ~CFile();               
    void ReadFile();         
    void WriteFile(string outputFilename);   
    void Calculate();   
    string  m_filename;
    int     m_numberInput;
    double* m_xData;         
    double* m_yData;
    int     m_numberOutput;
    double* m_xDataOut;     
    double* m_yDataOut;
};

CFile::CFile(string filename)
{
    m_filename = filename;
    string line;             
    ifstream myfile(m_filename.c_str());

    if (myfile.is_open())     
    {
        getline(myfile,line);    
        myfile.close();          
        stringstream Str;        
        Str << line; 
        Str >> m_numberInput;
        m_xData = new double[m_numberInput];  
        m_yData = new double[m_numberInput];
        cout << sizeof(m_xData) / sizeof(m_xData[0]) << endl;
    }
    else cout << "Unable to open file.\n";  
}

CFile::~CFile()
{ 
    delete[] m_xData; 
    delete[] m_yData;                                  
    m_xData = 0;                                 
    m_yData = 0;
    delete[] m_xDataOut; 
    delete[] m_yDataOut;                                  
    m_xDataOut = 0;                                 
    m_yDataOut = 0;
}

void CFile::ReadFile()
{
    ifstream infile(m_filename.c_str());
    string line;

    if (infile.is_open())
    {
        int x, y, i = 0;

        while (getline(infile,line))
        {
            infile >> x >> y;
            m_xData[i] = x;
            m_yData[i] = y;
            i++;
        }
        infile.close();
    }
    else cout << "Unable to open file.\n"; 
}

void CFile::WriteFile(string outputFilename)
{
    ofstream outfile(outputFilename.c_str());

    if (outfile.is_open())
    {
        for(int i=0; i < m_numberInput; i++)
            outfile << m_xDataOut[i] << " " << m_yDataOut[i] << endl;

        outfile.close();
    }
    else cout << "Unable to open file.\n"; 
}

void CFile::Calculate()
{
    m_xDataOut = new double[m_numberInput]; 
    m_yDataOut = new double[m_numberInput];

    for(int i=0; i < m_numberInput; i++)
    {
        m_xDataOut[i] = m_xData[i];
        m_yDataOut[i] = sqrt(m_yData[i]);
    }
}


int main()
{
    CFile file("Input.dat");
    file.ReadFile(); 
    file.Calculate(); 
    file.WriteFile("Output.dat");
    file.~CFile();
}

报错信息如下:

main(11915,0x7fff77d3d310) malloc: *** error for object 0x7f8a99403940: pointer 
being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

具有讽刺意味的是,这是几周前运行良好的代码。我更改了操作系统和编译器,现在不再更改了。我在其他线程中阅读了有关此错误的信息,但无法真正理解如何在我的代码中使用这些解决方案。代码读入一个数据文件,做某事。用它,然后将更改的值写入另一个文件。 分配错误在哪里? 非常感谢您的帮助! :-)

【问题讨论】:

  • 您在析构函数中删除了四个数组。但你并不总是初始化它们。你能指望什么?此外,您显式调用析构函数,但在退出范围时会再次调用它。你不需要那个析构函数调用。
  • 除了你的错误打破了这个程序中断,你还违反了三规则。而不是摆弄手动堆(de)分配,你真的应该使用 std::vector 来代替。
  • struct Point { double X,Y; }; typedef std::vector&lt;Point&gt; PointVector; PointVector calculate(const &amp;PointVector input){ ...};

标签: c++ class pointers allocation


【解决方案1】:

你的析构函数被调用了两次。您显式调用它,并且在退出 main() 时也会调用它。您应该删除您的显式 destrcutor 调用。

【讨论】:

  • file.~CFile(); 这是 OP 应该删除的行,你的意思是
【解决方案2】:

两个问题:

  • 您不必初始化所有四个指针,在这种情况下,将delete 应用于它们是不安全的。您可以通过在执行任何操作之前将它们初始化为 null 来解决此问题;或者,更好的是,用std::vector&lt;double&gt; 替换它们,这样你就不必乱用delete。这也将修复类的无效复制语义(它破坏了Rule of Three)以及如果构造失败可能导致的内存泄漏。
  • 您正在手动调用析构函数(file.~CFile(),在main 的末尾)。不要那样做:当程序离开变量的作用域时会自动调用析构函数,调用两次是错误的。

【讨论】:

    【解决方案3】:

    正如@claptrap 指出的那样,您的内存管理也有问题。

    1. 您应该迁移到 std::vector&lt;double&gt; 而不是原始的 double 数组和指针。您可以将vec.resize(N) 视为new double[N] 的变体,它永远不需要显式的delete[]

    2. 如果您在 Linux 上,最好在valgrind 下运行您的程序,它会自动跟踪内存分配/解除分配并指出任何无效的内存操作。我敢打赌你的 Linux 发行版有一个预编译的包。

    【讨论】:

      【解决方案4】:

      这是导致问题的原因

        delete[] m_xDataOut; 
        delete[] m_yDataOut;    
      

      你还没有在你的构造函数中初始化指针

      【讨论】:

      • 虽然总的来说你是对的,如果你遵循 RAII 你应该在你的构造函数中分配内存并在析构函数中释放,这不是 OPs 的问题,因为他在他的 Calcuate()函数,在他的例子中总是被调用。
      猜你喜欢
      • 2018-09-30
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2019-03-13
      • 1970-01-01
      相关资源
      最近更新 更多