c++ - 为什么 'allocate in one library and free in the other'是错误的

标签 c++ c android-ndk shared-libraries

Google 在 Android ndk guides site 中写道:

Memory allocated in one library, and freed in the other, causing memory leakage or heap corruption.

  1. 为什么?
  2. 总是正确的?

编辑

正如@Galik 所写,这句话的上下文是:

In C++, it is not safe to define more than one copy of the same function or object in a single program. This is one aspect of the One Definition Rule present in the C++ standard.

When using a static runtime (and static libraries in general), it is easy to accidentally break this rule. For example, the following application breaks this rule:

...

In this situation, the STL, including and global data and static constructors, will be present in both libraries. The runtime behavior of this application is undefined, and in practice crashes are very common. Other possible issues include:

  • Memory allocated in one library, and freed in the other, causing memory leakage or heap corruption.
  • Exceptions raised in libfoo.so going uncaught in libbar.so, causing your app to crash.
  • Buffering of std::cout not working properly.

最佳答案

它被认为是错误的一个可能原因是因为分配通常伴随着某种初始化,而释放则伴随着一些销毁逻辑。


理论:

主要的危险是不匹配的初始化/销毁逻辑。

让我们将两个不同的 STL 版本视为两个不同且独立的库。

考虑一下:每个库都允许您分配/取消分配一些东西。在获取资源后,每个图书馆都会以自己的方式对该事物进行一些内务处理,这些方式是封装的(阅读:你不知道,也不需要)。 如果每个人所做的内务处理有很大不同,会发生什么?


示例:

class Foo
{
private:
    int x;

public:
    Foo() : x(42) {}
};


namespace ModuleA
{
    Foo* createAFoo()
    {
        return new Foo();
    }

    void deleteAFoo(Foo* foo)
    {
        if(foo != nullptr)
            delete foo;
    }
}

namespace ModuleB
{
    std::vector<Foo*> all_foos;

    Foo* createAFoo()
    {
        Foo* foo = new Foo();
        all_foos.push_back(foo);
        return foo;
    }

    void deleteAFoo(Foo* foo)
    {
        if(foo != nullptr)
        {
            std::vector<int>::iterator position = std::find(all_foos.begin(), all_foos.end(), foo);
            if (position != myVector.end())
            {
                myVector.erase(position);
            }
            delete foo;
        }
    }
}

问题:如果我们执行以下操作会发生什么情况?

Foo* foo = ModuleB::createAFoo();
ModuleA::deleteAFoo(foo);

答案:ModuleB 现在有一个 dangling pointer . 这可能会导致各种可怕且难以调试的问题。 我们也没有让 all_foos 变小,这可能被认为是内存泄漏(每次指针的大小)。


问题:如果我们执行以下操作会发生什么情况?

Foo* foo = ModuleA::createAFoo();
ModuleB::deleteAFoo(foo);

答案:看起来……没有什么不好的事情发生! 但是,如果我删除 if (position != myVector.end()) 检查怎么办?那我们就有问题了。 STL 可能会以优化的名义这样做,所以...

关于c++ - 为什么 'allocate in one library and free in the other'是错误的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51232916/

相关文章:

c - 如何使用 scanf (不是 fgets)读取文本行?

c - makefile - 如何从变量中排除文件扩展名后缀

c++ - 如何使用 VTK 原始保存 DICOM 系列

c++ - *您*使用 C++ ABC 构造函数做什么?

c++ - 获取派生初始化列表中父级的地址

c++ - 如何结合 constexpr 和矢量化代码?

创建一个可以根据参数省略一行的宏

android - 如何将 NDK 库导入 Eclipse

android - glTexImage2D 使用 OpenGL ES 2.0 抛出错误 0x501 Android NDK 程序

android - 如何将 Android Surface 对象转换为原生 Surface