更新函数调用中的静态成员会导致崩溃

时间:2012-01-16 20:02:32

标签: c++ linux static constructor

我有一个polymer的课程static int count。 当我创建一个新的polymer以添加到指针数组时,我使用count在数组中找到正确的位置,然后更新构造函数中的count。在Windows中编译时它起作用了。但是,在Linux(Ubuntu)中进行编译时,除非我从构造函数中删除count的更新,否则它会崩溃。

Windows和Ubuntu中的工作:

polymerPointer[polymer::count] = new polymer();
polymer::count++;

当构造函数不更新静态变量时(见下文)

polymer::polymer(){
    //sets up lots of variables but doesn't update the static member
};

Ubuntu中的崩溃(适用于Windows):

polymerPointer[polymer::count] = new polymer();

构造函数何时更新静态变量(见下文)

polymer::polymer(){
    //sets up lots of variables and then updates the static member
    count++;
};

我可以重写代码,但我不必记得单独更新变量,这就是我将更新放在构造函数中的原因。关于出了什么问题的任何想法?

5 个答案:

答案 0 :(得分:2)

你正在达到未定义的行为。

以下内容:

polymerPointer[polymer::count] = new polymer();
polymer::count++;

不等于

polymerPointer[polymer::count] = new polymer();

其中polymer()递增polymer::count

未定义的行为是因为您正在修改某个值并在同一语句中使用该值:

  

§1.9p15如果标量对象的副作用是相对无序的   对同一个标量对象或值的另一个副作用   使用相同标量对象的值进行计算,行为是   未定义。

可能发生的是计数递增,然后将对象放置在数组中的新位置。现在代码将访问留下的空白点,就像它持有有效指针一样,或者当你到达数组的末尾时,你可能会尝试将指针放在数组的边界之外。

将计数增量放在与实际插入数组的位置不同的位置是不好的设计。你应该做的是编写一个静态成员函数,它将元素添加到数组并更新计数,然后使用它而不是手动创建对象并手动将其放入数组中,同时期望计数自动更新。

class polymer {
    static void create_new_polymer() {
        polymerPointer[polymer::count] = new polymer();
        count++;
    }
};

更好的方法是使用vector并让它管理自己的数量:

polymerPointer.push_back(new polymer());

答案 1 :(得分:1)

编译器可以在polymerPointer[polymer::count]之前合法地评估new polymer();,或者按照自己的意愿合法评估polymer::count。这意味着您不能依赖std::vector<std::unique_ptr<Polymer>>作为原始值。您必须使用更具确定性的内容,例如{{1}}?

答案 2 :(得分:1)

这可能是由于未初始化的变量。尝试在调试器中单步执行代码,或者只打印出count的值。

您还可以检查polymerPointer是否指向已分配的内存(您为存储分配了多少内存,是否足以支持count的所有值?)。

答案 3 :(得分:1)

您的问题是标准不保证您的语句执行顺序,因此polymerPointer[polymer::count] = new polymer();可能会在执行polymer::count之前或之后评估new polymer();

如果您更改了polymer::count构建函数中的polymers并且polymer::count之后评估new polymer(),那么您显然会跳过索引,这可能会导致您的崩溃。

但是你真的有任何迫切的理由在这里使用看起来像c风格的数组,而不是使用std::vector(不需要额外的count变量)吗?此外,如果您有选择,那么您真的不应该使用手动内存管理,因此如果您有权访问C ++ 11,std::unique_ptrstd::shared_ptr,请使用std::tr1::shared_ptrboost::shared_ptr除此以外。如果你正在使用提升boost::ptr_vector也是一个选项

答案 4 :(得分:0)

最简单的解决方法是将该分配分成两部分,从而引入排序

polymer*& insert_point = polymerPointer[polymer::count];
insert_point = new polymer();

其他答案解释了推理。