C++ 删除时,共享ptr上的新位置会导致seg故障
编辑解决方案:: 事实上,我只是忘记了复制构造函数中的新位置>技术问题: 工会不会, 未初始化, 三条规则:不正确负责复制 设计问题: 将类型表示为数字。将类型表示为类型。 保留从编写代码中获得的知识,然后从头开始C++ 删除时,共享ptr上的新位置会导致seg故障,c++,c++11,std,C++,C++11,Std,编辑解决方案:: 事实上,我只是忘记了复制构造函数中的新位置>技术问题: 工会不会, 未初始化, 三条规则:不正确负责复制 设计问题: 将类型表示为数字。将类型表示为类型。 保留从编写代码中获得的知识,然后从头开始 在你发布真正的代码之前,几乎没有什么有意义的话可以说,例如swithc永远不会编译:你发布的不是真正的代码。如果你是用C++03编译的,代码是非法的,因为 C++03不允许具有非平凡默认构造函数的类型, 复制中的构造函数、赋值运算符或析构函数 工会。对于C++11,代码是非法的,因为
在你发布真正的代码之前,几乎没有什么有意义的话可以说,例如swithc永远不会编译:你发布的不是真正的代码。如果你是用C++03编译的,代码是非法的,因为 C++03不允许具有非平凡默认构造函数的类型, 复制中的构造函数、赋值运算符或析构函数 工会。对于C++11,代码是非法的,因为如果 如果包含上述任何内容,编译器将删除 工会的相应成员。所以你们的工会没有违约 构造函数、复制构造函数、赋值或析构函数。哪一个 意味着你不能实例化它,或者以任何方式使用它。哪一个 意味着A::Aint所需的默认构造函数没有 存在,并且当您定义此 函数或函数的任何构造函数 如果编译器编译此类代码,则意味着编译器 没有正确地实施新的工会内容,因此 你不能用它 关于实际发生的事情:我怀疑 编译器正在的复制构造函数中使用按位复制 而不是拒绝生成它。vec.emplace_backtmp 使用复制构造函数在vec中创建新元素。 按位复制意味着您将得到两个 指向同一对象但同时指向两个对象的共享\u ptr 数到1。第一个正确地破坏,而 第二个访问已删除的内存。轰 解决问题的最简单方法是使用 variant,意思是在联合体中定义结构 在联盟之外的某个地方,给他们起个名字。如果为了 由于某些原因,您无法使用Boost,因此使用Boost相对来说是微不足道的 按照你正在做的事情,用手实施。在里面 联合本身,您只有未签名的字符标记[ sizeofTokenType];等,对于每个非POD成员 如有必要,可增加构件,以确保在most上对齐 处理器,一个双工就可以了。然后使用 重新解释数组名称上的\u cast以获取指向 所需类型、用于初始化它的新位置和显式 破坏来破坏它,就像你做的那样。 然后实现一个复制构造函数和一个赋值 操作员,并考虑到类型 没那么难。我已经做过一两次了:为了 解析器中的标记,用于我们从Excel中获取的建模表,
等等。为什么要使用新位置?为什么不简单地分配结果?看起来像是教科书上的过度思考案例?std::shred_ptr是非pod类型,因此不能在联合内部使用。在联合体内部使用非POD会产生未定义的行为。@ArneMertz我使用未定义的联合体c++11只是为了说明:联合体成员具有非平凡构造函数等不是未定义的行为。该错误需要诊断。在C++11中,如果有人试图在没有任何参数的情况下构造具有非平凡默认构造函数的成员的联合,则需要进行诊断。例如,在A的初始化过程中,有一些特殊情况下,歧视工会是合适的。语义值可能具有不同类型的语法分析器中的标记就是一个很好的例子。@JamesKanze:我同意,这个例子涉及到标记,因此人们可能会马上想到这一点。但事实并非如此。不确定另一种情况是什么,你能想出一个不太具描述性的名字吗,但事实并非如此。这段代码中的联合是愚蠢的,我遇到的另一个例子是处理来自Excel、Python或Mathematica的数据。所有这些都允许混合类型的表/列表。在他的实际例子中,单词token出现在一些名字中,所以我猜这就是他想要做的。但我在他的法典中有点同意工会;当需要区分联合时,不能使用匿名结构的匿名联合。考虑到围绕它所要做的一切,您可以用一个显式名称来定义每个类型。@Cheersandhth.-Alf thx,但这不是答案。我需要联合,所以不要说ro不使用它们。首先我发布最小的代码,然后是真实的代码。睁开你的眼睛。注意,给定的语法错误的代码不能编译,所以我认为从它的编译与否属性可以说很少。另外,我会犹豫是否推荐使用例如boost::variant来解决问题,因为我们不知道工会要解决什么问题。这不是通常的象征性的东西。@Cheersandhth.-Alf-注意,他后来添加了他的原始代码,因为我们从错误的示例代码中得出了错误的结论。我不认为
蚂蚁使用boost。C++11成功。@Krozark Boost是一个优秀的库,它扩展并补充了C++11的许多功能。C++ 11中的许多新库特征来自Boost,并且同样可能出现在下一版本的C++标准中。我想说的是,如果标准中的某个功能使用了其他增强功能,您可以同时使用这两种功能。@JoachimPileborg是的,我知道。但事实上我不需要升压来解决这个问题所以。。。
class B; //on other file
class A {
public:
A(int type) : type(type)
{
switch(type)
{
case TOKEN:
{
for(int i=0;i<4;++i)
new(&token.h[i].link) shared_ptr<B>; //< init the ptr on the addr (because of union)
}break;
case OTHER: {}break;
}
}
~A()
{
switch(type)
{
case TOKEN:
{
for(int i=0;i<4;++i)
{
/*option 1*/ token.h[i].link.~shared_pt<B>(); //< Make seg fault
/*option 2*/ token.h[i].link.reset(); //< ok
}
}break;
case OTHER: {}break;
}
}
}
enum {TOKEN=0,OTHER} type;
union {
struct {
double score;
struct {
std::shared_ptr<B> link;
double to_find;
} h [4];
}token;
struct {
//else
} other;
}
};
void f()
{
vector<A> vec;
A tmp = A(A::TOKEN);
vec.emplace_back(tmp);
}
class stack_token {
public:
stack_token();
stack_token(const stack_token& other);
stack_token(const int i,Parser::peptide::peak* data); //peak
stack_token(const int i,const double e,AnalyseurPeptide::stack_token* peak); //aa
stack_token(const int i); //aa pour boucher un trou
stack_token(const double score); //HEADER
~stack_token();
stack_token& operator=(const stack_token& other);
inline stack_token* get_peak_stack_NULL() {
stack_token* res = aa_token.pt_data;
aa_token.pt_data=NULL;
return res;
};
void __print__() const;
enum Type {UNKNOW=-1,AA_TOKEN=0,AA_HOLD_TOKEN,/*AA_LIST,*/PEAK_TOKEN, HEADER_TOKEN} type;
union {
struct {
int index;
double error;
stack_token* pt_data;
} aa_token;
struct{
double error;
stack_token* pt_data;
std::vector<int> aa_index;
} aa_hold_token;
struct {
int index;
Parser::peptide::peak* pt_data;
} peak_token;
struct {
double score;
struct {
std::shared_ptr<std::list<list_arg> > link;
double to_find;
} holds [Parser::peptide::SIZE];
} header_token;
};
};
stack_token::~stack_token()
{
switch(type)
{
case AA_TOKEN:
{
if(aa_token.pt_data != NULL)
delete aa_token.pt_data;
}break;
case AA_HOLD_TOKEN :
{
aa_hold_token.aa_index.~vector<int>();
}break;
case PEAK_TOKEN :
{
}break;
case HEADER_TOKEN :
{
for (int i=0;i<Parser::peptide::SIZE;++i)
header_token.holds[i].link.reset();//~shared_ptr<std::list<list_arg> >();
}break;
default : break;
}
};
stack_token::stack_token()
{
this->type = UNKNOW;
};
stack_token::stack_token(const int i,Parser::peptide::peak* data) //peak
{
this->type=PEAK_TOKEN;
peak_token.index = i;
peak_token.pt_data = data;
};
stack_token::stack_token(const int i,const double e,AnalyseurPeptide::stack_token* peak) //aa
{
this->type=AA_TOKEN;
aa_token.error =e;
aa_token.index = i;
aa_token.pt_data = peak;
};
stack_token::stack_token(const int i)
{
this->type=AA_HOLD_TOKEN;
aa_hold_token.error = 0;
aa_hold_token.pt_data = this;
new(&aa_hold_token.aa_index) vector<int>();
};
stack_token::stack_token(const double score) //HEADER
{
this->type = HEADER_TOKEN;
header_token.score = score;
for (int i=0;i<Parser::peptide::SIZE;++i)
new (&header_token.holds[i].link) shared_ptr<list<list_arg> >;
#warning "add to_find init"
};
void save_stack(const std::list<stack_token*>& search, std::list<std::vector<stack_token> >& res)
{
vector<AnalyseurPeptide::stack_token> l;
auto i=search.begin();
auto end = search.end();
stack_token tmp = stack_token(0.f); /* if I remove this */
l.emplace_back(tmp); /* and this, all is ok */
while(i!=end)
{
l.emplace_back(**i); //< fail here
++i;
}
res.emplace_back(l);
}