我有一个测试随机失败,我怀疑由于std :: set中的对象顺序在指针值上排序。 但是,在我当前的exe上,测试总是通过。有没有办法可以"混合"指针创建所以我的集合中的对象顺序在两次运行之间是不同的?
换句话说,是"排序顺序" (p1< p2)指针确定给定C ++代码,或者不同的编译或不同的运行可以有不同的排序顺序?
例如,在此代码中,添加" p1b.reset(nullptr)"在p1和p2之间创建将反转p1 / p2"排序顺序" 。有没有其他方法来影响这个顺序,而不更改源代码?
int main(void)
{
std::unique_ptr< MyClass > p1b(new MyClass());
//Lot of code, with memory allocated/deallocated
std::unique_ptr< MyClass > p1(new MyClass());
//p1b.reset(nullptr);
//Lot of code, with memory allocated/deallocated
std::unique_ptr< MyClass > p2(new MyClass());
std::cout << "p1: " << p1.get() << std::endl;
std::cout << "p2: " << p2.get() << std::endl;
}
给出:
p1: 0x171c030
p2: 0x171c050
使用&#34; p1b.reset(nullptr)&#34;评论说:
p1: 0x21f9030
p2: 0x21f9010
答案 0 :(得分:2)
编辑2 :根据您的修改:https://stackoverflow.com/revisions/37027675/3
换句话说,是指针的“排序顺序”(
p1 < p2
) 确定性的给定C ++代码,或不同的编译或 不同的运行可以有不同的排序顺序吗?
是的,它们可以有不同的顺序,因为 - 当你在堆上分配时,内存分配器返回的指针地址的“连续顺序”是不可保证的,所以,是的,它可以随时改变。阅读答案的其余部分。
编辑1 :根据您的修改:https://stackoverflow.com/revisions/37027675/2
例如,在此代码中,在
p1b.reset(nullptr)
和之间添加p1
p2
创建将反转p1
/p2
订单。还有其他办法吗? 影响这个命令?
不,它不会“反转”创建顺序,您销毁p1
并创建另一个对象(可能相等)并取代p1
。阅读初步答案..
初步回答
有没有办法可以“混合”指针创作所以顺序 我的集合中的对象在两次运行之间有所不同吗?
有可能,你的内存分配器以连续的方式分配内存,所以如果你在一个线程程序中连续分配元素,它们可能会在一连串的内存地址中。但如果是关于绝对指针地址,由于Address space layout randomization
,它们可能会在程序的每次运行中处于“不同的”绝对偏移量如果您希望连续元素的内存地址是随机的或按特定顺序,则必须以随机方式创建它,或者只是按照您想要的顺序创建...
对于一个随机的方式...... ...我的头脑:也许,为你想要创建的对象生成std::vector
个索引;随机化(或随机)vector
然后运行创建对象的向量元素。
我上面的回答是基于你所说的怀疑。但同样,我对此感到不安:
我有一个随机测试失败,我怀疑是因为一个对象的顺序 std :: set在指针值上排序。但是,在我当前的exe上, 测试总是通过。
检查Undefined Behaviors并通过代码运行内存工具和静态分析器。
答案 1 :(得分:-2)
在堆上分配对象的顺序完全取决于您。顺便说一句,你确实记得std::set
当被销毁时只调用它的内容析构函数,如果是指针则意味着指针根本就不存在,而它们指向的对象仍然存在于堆中并且可能已成为悬空引用,对吧?如果您在std
容器中存储普通指针,请不要忘记手动delete
。