Добрый час.
| "Есть такой код." |
| #include <iostream>
class Object
{
public:
Object()
: p(nullptr)
{
int n = 0;
n++;
}
virtual ~Object()
{
if (p) {
delete p;
}
}
private:
int * p;
};
class IPrimitive : public virtual Object
{
};
class ITrailerable : public virtual Object
{
};
class IStableInfo : public virtual Object
{
};
class Primitive : public virtual IPrimitive, public virtual ITrailerable
{
private:
int arr[100];
};
class IObject : public virtual Object
{
};
class ISerializable : public virtual Object
{
};
class IntermObject : public Primitive, public virtual IObject, public virtual ISerializable, public IStableInfo
{
public:
IntermObject()
{
}
IntermObject(int v)
: IntermObject()
{
throw "uups";
}
IntermObject(int v, int t)
: IntermObject(v)
{
}
~IntermObject()
{
int n = 0;
n++;
}
private:
int n;
bool b;
};
class IPage : public virtual ITrailerable
{
};
class IPages : public virtual Object
{
};
class IPageTreeNode : public virtual IObject, public IPage, public IPages
{
};
class PageTreeNode final : public IntermObject, public IPageTreeNode
{
public:
PageTreeNode()
: IntermObject(10, 20)
{}
};
int main()
{
std::cout << "Hello !\n";
try
{
new PageTreeNode();
}
catch (...)
{[img][/img]
std::cout << "Catch!\n";
int n = 0;
n++;
}
std::cout << "World!\n";
}
|
| |
Проблема в том что при выборосе исключения:
IntermObject(int v)
: IntermObject()
{
throw "uups";
}
В деструкторе Object происходит AV (Windows — cl) или Seg.Fault (Linux — gcc)
| "Из за неправильного смещения:" |
| |
| |
Вот такое изменение:
class PageTreeNode final : public IntermObject, public virtual IPageTreeNode
Исправляет проблему с падением, но приводит к двойному вызову деструктора ~Object() (конструктор вызывается 1 раз)
Мне не очень понятно зачем здесь виртуальное наследование, и правы ли компиляторы?
Другой пример:
struct Object
{
Object() = default;
virtual ~Object() = default;
};
struct IntermObject : public virtual Object
{
IntermObject() = default;
IntermObject(int v) : IntermObject() {}
};
struct PageTreeNode : public IntermObject
{
PageTreeNode() : IntermObject(1) {}
};
int main()
{
new PageTreeNode();
}
Уже не приводит к seg. fault у gcc, но приводит к AV у cl (при запуске исполняемого файла).
Замена = default на обычную имплементацию "по старинке" решает проблему с cl.
cl.exe — Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27031.1
gcc — из
https://www.onlinegdb.com