C++在库之间混合新建/删除?

vfh0ocws  于 2023-11-19  发布在  其他
关注(0)|答案(6)|浏览(115)

如果我在我的库中使用new关键字(它与我的主应用程序构建方式不同),当我在我的主应用程序中使用delete删除它时,是否有可能出现崩溃/错误?

vcirk6k6

vcirk6k61#

这要看情况而定。如果你说的是静态库,那么你很可能是对的--代码将在与主程序相同的上下文中运行,使用相同的C运行时库。这意味着newdelete将使用相同的堆。
如果你说的是一个共享库(DLL),那么你可能就不太好了。在DLL中运行的代码可能使用不同的C
运行时库,这意味着堆的布局将不同。DLL可能使用完全不同的堆。
在DLL分配的指针上调用delete(在主程序中)(反之亦然)将导致(最好的情况下)立即崩溃或(最坏的情况下)内存损坏,需要一段时间才能跟踪。
你有几个选择。第一个是使用“工厂方法”模式来创建和删除这些对象:

Foo *CreateFoo();
void DeleteFoo(Foo *p);

字符串
这些不应该在头文件中实现。
或者,你可以在对象上定义一个Destroy方法:

class Foo
{
    ~Foo();

public:
    virtual void Destroy();
};


.同样,不要在头文件中实现它。你可以这样实现它:

void Foo::Destroy()
{
    delete this;
    // don't do anything that accesses this object past this point.
}


请注意,Foo的析构函数是私有的,因此必须调用Foo::Destroy
Microsoft COM做了类似的事情,它定义了一个Release方法,当对象的引用计数降为零时删除该对象。

ruoxqz4g

ruoxqz4g2#

是的。特别是你会看到调试/发布堆不同的问题,如果你的库使用了placement new,或者任何自定义堆,你都会有问题。调试/发布问题是目前为止最常见的。

thigvfpy

thigvfpy3#

是的,你会的。一个简单的解决方案是在你的库中提供可以从主应用程序调用的Create和Delete函数。Create函数将执行new并返回一个指针,该指针稍后被传递到Delete函数以进行删除。

z0qdvdin

z0qdvdin4#

这是一个我只在Windows上见过的问题。
Unixish系统没有强制共享库链接到同一程序中同一库的不同版本的习惯,所有加载的符号都是全局可见的。这意味着如果一个对象在代码的一部分中被分配,而在另一部分中被删除,两者都使用相同的系统库来完成。
我不得不说,Windows用它的各种C运行时DLL创建的这个问题对于C程序员来说真的很烦人,也很不自然。它有像strdup这样的函数,可以对字符串进行malloc,并期望程序员对其调用free()。但是在Windows上的你自己的库中做同样的事情,只需要等待爆炸。你也必须等待,因为它不会在开发过程中发生,而只会在你把编译好的DLL交给其他可怜的sap之后发生。

zbq4xfa0

zbq4xfa05#

Old New Thing之前已经讨论过这个问题,他还列出了微软的主要解决方案。

jtw3ybtb

jtw3ybtb6#

你说得很对,这确实是个问题,但对于大多数情况,有一个比其他答案(到目前为止)提出的更简单的解决方案。你可以继续自由地使用new和delete--你所需要做的就是为库中每个可能跨DLL边界使用的类重载new和delete。
就我个人而言,我只是定义了一个简单的类来提供所需的功能:

class NewDelete
{
    public:
        void *operator new (size_t size);
        void operator delete (void *memory);
        void *operator new (size_t size, void *ptr);
        void operator delete (void *memory, void *ptr);
};

字符串
只要这四个成员函数都定义在同一个DLL中,那么从这个类派生的任何类都自动是“DLL安全的”-- new和delete可以在它们上正常使用,而不必担心DLL边界。

相关问题