C ++赋值构造函数Valgrind错误

时间:2019-01-08 11:18:28

标签: c++ memory valgrind

我正在尝试创建自己的载体以用于练习目的。一切都很好,但是现在我想测试向量,该向量也包含分配内存的对象。

我的问题在于该类(1)的赋值构造函数,该构造函数在测试向量的构造函数中调用。

test_vec.h:

#ifndef TEST_VEC
#define TEST_VEC

#include <cstddef>

template<class T>
class vector
{
public:
    explicit vector(size_t count, const T& value)
        : m_size(count)
        , m_capacity(count)
        , raw_data(static_cast<T*>(operator new(count * sizeof(T))))
    {
        for (size_t i = 0; i < count; ++i) {
            raw_data[i] = value; //(1) Calls the assignment constructor
        }
    }

    ~vector()
    {
        //clearing objects not implemented yet
        operator delete(raw_data);
    }
private:
    size_t m_size;
    size_t m_capacity;
    T* raw_data;
};

#endif

main.cpp:

#include "test_vec.h"

class TestClass {
public:
    TestClass(size_t number) {
        testMem = new size_t[10];
        for (size_t i = 0; i < 10; ++i) {
            testMem[i] = 0;
        }
        testMem[1] = number;
    }
    TestClass(const TestClass& other) {
        testMem = new size_t[10];
        for (size_t i = 0; i < 10; ++i) {
            testMem[i] = other.testMem[i];
        }
    }
    TestClass& operator=(const TestClass& other) {        
        if (this != &other) {
            //I know this is not exception safe at the moment
            delete[] testMem; //(2) delete earlier assigned memory 
            testMem = new size_t[10];

            for (size_t i = 0; i < 10; ++i) {
                testMem[i] = other.testMem[i];
            }
        }
        return *this;
    }
    ~TestClass() {
        delete[] testMem;
    }
    size_t number() const {
        return testMem[1];
    }
private:
    size_t* testMem = NULL;

};

int main() {
    TestClass t1(4); //(4)
    TestClass t2(3);

    t1 = t2;

    vector<TestClass> vec_TestClass(1, TestClass(3)); //(3)
}

一切都很好。但是valgrind在(3)处抱怨“有条件的跳跃或移动取决于未初始化的值”。这是正确的,因为在我要分配对象的那一刻,testMem尚未初始化。但是,当我评论删除(2)时,我从(4)中收到内存泄漏。这也是正确的。

如何解决此问题,以便处理两种情况?

感谢和问候

3 个答案:

答案 0 :(得分:2)

没有“分配构造函数”之类的东西。我知道您可能想弄乱未初始化的内存,但是您仍然需要调用适当的构造函数。在您的情况下,最简单的方法是使用std:::uninitialised_fill_n

#include <memory>

explicit vector(size_t count, const T& value)
    : m_size(count)
    , m_capacity(count)
    , raw_data(static_cast<T*>(operator new(count * sizeof(T))))
{
    std::uninitiliased_fill_n(raw_data, count, value);
}

还请注意,向量析构函数还需要销毁它构造的所有对象。

答案 1 :(得分:1)

为什么使用此static_cast<T*>(operator new(count * sizeof(T)))而不是正确的new T[count]?您实际上从未创建任何TTestClass也不是无关紧要的,因此确实需要构造它。 Valgrind似乎知道这一点。

operator newoperator delete用于分配器,而不用于用户。他们只是创建一个内存块,没有对象。使用newdelete(或者在标准代码中,使用标准容器!)。

此外,您的vector类没有副本构造函数。因此,vector的任何副本都具有未初始化的无效raw_data成员指针。在您的测试用例中,这不是问题,但总的来说是一个问题。

此外,没有赋值构造函数之类的东西。要么构造,要么分配!

答案 2 :(得分:-1)

好的。我认为它称为赋值运算符。错误是TestClass没有默认构造函数。我修好了,一切顺利。我用rihgt函数替换了new和delete运算符。对于这个小例子,我删除了向量。复制构造函数也是如此。

谢谢。我需要默认构造函数的提示是解决方案。