gpt4 book ai didi

c++ - 在 Visual C++ 中与虚拟继承层次结构一起使用时放置新崩溃

转载 作者:行者123 更新时间:2023-11-30 01:41:26 24 4
gpt4 key购买 nike

我在 C++ 中对一些类使用虚拟继承。它目前正在崩溃崩溃。它似乎在在线编译器中编译得很好,但是当我在 Visual Studio 中运行时,它崩溃了。

我有一个纯虚基类,它实际上被它的实现所继承。然后我有一个定期从实现继承的第三个类。我正在使用一个内部系统来创建和释放内存。在引擎盖下,它使用了一个新的布局和一个对齐的 malloc。然后它使用 free 来释放内存。我已经创建了这个最小示例。这不完全是我在做什么,但我似乎遇到了类似的问题。

#include <iostream>
#include <string>

int main()
{
class Animal {
public:
Animal() { }
virtual ~Animal() { }
virtual void eat() { }

};

class Mammal : public virtual Animal {
public:
virtual void breathe() { }

};

class WingedAnimal : public virtual Animal {
public:
virtual void flap() { }
};

// A bat is a winged mammal
class Bat : public Mammal, public WingedAnimal {

};

Animal* bat = new(malloc(sizeof(Bat))) Bat;
bat->~Animal();
free(bat);
printf("Done!");
}

如我所说,此示例将在在线编译器中打印“完成”。但是在 Visual Studio 2015 中,它似乎在没有 bat 对象时崩溃。我对虚拟继承和安置很陌生。有人看到问题了吗?

最佳答案

malloc返回一些新的内存地址,operator new放置一个 Bat在该地址,并转换为 Animal* 调整地址。现在 bat malloc 内某处的变量点堵塞。 free这是不可能的。

Bat* bat0 = new(malloc(sizeof(Bat))) Bat;
Animal* bat = bat0;
std::cout << bat0 << " " << bat << "\n";

gcc打印两个相同的地址,而 VC++打印两个不同的。即使不涉及多重继承,这两种行为都是完全正常的并且是标准允许的。大多数编译器实际上不会调整具有单一继承的地址,但也有一些异常(exception)。

为了安全起见,不要指望这两个地址相同。

可以通过动态转换为 void* 来恢复原始地址:

  free(dynamic_cast<void*>(bat));

应该没问题。当然,像往常一样,动态转换需要一个虚函数才能工作。

更新:dynamic_cast<void*>恢复初始指针,但是 free使用 VC++ 时仍然会崩溃。我不知道为什么。

在 C++ 程序中集成第三方内存管理器的正确方法是重载 operator newoperator delete

void* ::operator new(size_t sz) { return my_managed_malloc(sz); }
void ::operator delete (void* ptr) { return my_managed_free(ptr); }

将它们放在您程序的任何一个 C++ 文件中(如果您有 DLL,则在所有 DLL 中)并正常使用 C++,没有定义不当的指针技巧。

欲了解更多信息,http://en.cppreference.com/w/cpp/memory/new/operator_new .

关于c++ - 在 Visual C++ 中与虚拟继承层次结构一起使用时放置新崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41246633/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com