【问题标题】:Inconsistent operator new/delete calling不一致的运算符 new/delete 调用
【发布时间】:2011-01-07 12:03:00
【问题描述】:

我在调用我的重载运算符 delete 但不是我的 operator new 的动态链接库时遇到了一些问题。我的 exe 看起来像这样:

class A {
public:
    void func() {
        t = dynLib::Type::CreateObject();
    }
    dynLib::Type t;
};

void main() {
    A a;
    a.func();
}

然后我有一个静态链接库,其中有我的全局重载运算符 以及导致问题的动态链接库。基本上发生的情况是,dynLib::Type 类型包含一个 std::vector,它在其构造函数中添加一个元素。所以类型看起来像这样

class Type {
public:
    Type() {
        v.push_back( T() );
    }

    std::vector< T > v;
};

调用 func() 时,会创建一个新的 Type 实例,通过值传递,然后分配给 t。在那里工作的 operator= 也通过其 operator= 复制 std::vector。这反过来又在 t 中的旧 std::vector 上调用 deallocate,因为它已经在其构造函数中添加了一个元素。这个取消分配调用最终调用我的操作员删除。问题是,我的 operator new 从未被调用过,所以它正在删除一个完全不同的内存空间中的指针(内存日志显示了这一点)。

现在,我可能只是错过了一些东西。由于上面的 A 类包含一个 dynLib::Type 对象,它可能会在我的 operator new (来自静态库)被链接之前构建。这甚至可能吗?我不太确定在什么时候调用了组合 dynLib::Type 的构造函数。动态库使用默认的 stl 分配器,因此它不会做任何奇怪的事情。

我尝试在没有动态链接库的情况下重新创建相同的情况,只需在我的 exe 中添加 Type 类。但这不会导致问题,所以它让我相信它一定与链接顺序有关。

【问题讨论】:

    标签: c++ windows dll static-libraries new-operator


    【解决方案1】:

    这是坏事。您实际上是在跨 DLL 边界使用 STL 对象。这是一个很大的禁忌,会继续让你头疼。链接问题的最可能来源是可执行文件和 DLL 如何使用 CRT。如果一个使用静态 (/MT) 而另一个是动态 (/MD),您会看到各种奇怪的现象,而重载运算符 new 通常是第一个出现故障的运算符。

    如果 CRT 全面一致,那么它应该可以工作,但仍然不建议将 DLL 当作静态库使用。

    尝试重构代码,这样您就不必在 DLL 之外构造 Type,看看是否会变得更好。

    【讨论】:

    • 库和我的 exe 都使用动态 CRT。而我最好奇的是为什么它只使用我的操作员删除而不是新的?当我在上面调用 func() 时,CreateObject() 函数在 dll 中,那不应该让它使用自己的 new/delete 吗?
    • 但随后它被分配给可执行文件中的t,因此它调用了可执行文件中的运算符new。理论上它应该只是工作,但由于某种原因它没有。这是一个常见问题:stackoverflow.com/questions/1085873/dll-memory-manager-mixup
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 2014-03-26
    • 2015-01-16
    • 2011-06-11
    • 1970-01-01
    • 2013-03-12
    • 2023-03-23
    相关资源
    最近更新 更多