使用已定义结构的向量到达未初始化的内存

时间:2014-06-11 21:43:43

标签: c++ c++11

我使用vector的length和value构造函数创建了一个名为xor_funcs的bitpacked向量的向量。 这是失败的测试:

TEST(vectorInit, size3) {
    const xor_func temp{false, {0,0,0}};
    vector<xor_func> arr{3, temp};
    for(xor_func& f : arr) {
        EXPECT_EQ(3, f.size()) << f;
    }
    for(int i = 0; i < 3; i++) {
        ASSERT_EQ(3, arr[i].size()) << "for i=" << i;
        arr[i].set(i);
    }
}

似乎size()调用正在访问未初始化的内存,对于长度为3或更长的向量,而不是大小为2的向量.Valgrind确认内存最近不是堆栈&#39; d,malloc&#39 ; d或免费&#39; d。

xor_func定义如下:

class xor_func {
    private:
        boost::dynamic_bitset<> bitset;
        bool negated;
    public:
        xor_func(const bool neg, const std::initializer_list<int> lst); 
        // That's defined in cpp

        xor_func(const size_t size) : bitset(size), negated(false) {}

        // Disallow the trivial constructor, since I don't want
        // any 0 length xor_funcs existing by default.
        // xor_func() : bitset(), negated(false) {}

        xor_func(const bool negated, const boost::dynamic_bitset<> bitset)
            : bitset(bitset), negated(negated) {}
        // That's all the constructors.

        // Snip
}

我没有对默认副本和移动构造函数做任何事情。

发生了什么,为什么我的测试失败了?

1 个答案:

答案 0 :(得分:5)

正如dyb所说,vector<xor_func> arr{3, temp};被解释为 vector<xor_func> arr({xor_func{3}, temp}),因为3可以隐式地由构造函数转换为xor_func,然后它可以选择要调用的构造函数的初始化列表版本。

如果你看一下Is C++11 Uniform Initialization a replacement for the old style syntax?,你会发现统一初始化语法的一个缺点就是这个bug。一个更简单的例子是

// std::string constructor prototype for reference
// fill (6) 
string (size_t n, char c);

void main() {
    string myString{65, 'B'};
    cout << myString << endl;
}

这将打印出“AB”,而不是“BBBBBB ... BBB”,因为它可以将65转换为'A',然后就好像我们写了myString{'A', 'B'}一样。要解决此问题,请不要尝试为此调用使用统一初始化语法,并将其替换为

string myString(65, 'B');

我可以修复此错误的另一种方法是将构造函数xor_func(const size_t size)更改为explicit xor_func(const size_t size),这会阻止编译器将3隐式转换为xor_func。< / p>

哦,还有另一个很好的答案What does the explicit keyword mean in C++