Ans*_*Tan 5 c++ linux dll shared-libraries
从这个环节,我知道我们(应用程序)应始终不从DLL删除堆内存分配,因为堆内存管理是不同的。
我有几个问题:
1.) .so 文件 (Linux) 怎么样,是一样的情况吗?
2.) 无论如何要确保应用程序和库(.dll 和 .so)使用相同的堆内存管理器或使用相同的堆内存部分?所以我们可以分别删除和新建(在 .dll/.so 中新建,在应用程序中删除)。
谢谢你。
1.) .so 文件(Linux)怎么样,是同样的情况吗?
是的,使用与最终链接的程序不同的标准 C++ 库实现构建的库可能会以稍微不同的方式进行分配。g++'slibstdc++和clang++'slibc++是两种不同实现的示例。它们可能100% ABI 兼容 - 但第三个未知库可能不是。
2.)是否有办法确保应用程序和库(.dll 和 .so)使用相同的堆内存管理器或使用相同的堆内存部分?所以我们可以分别删除和新建(在.dll/.so处新建,在application处删除)。
不,编译到库中的内容就是库将使用的内容,除非有一种方法可以在加载库时对其进行初始化,告诉它使用特定的堆管理器。
请详细解释一下。我想知道 .so (Linux)是否只使用一个堆管理器来处理应用程序和 .so (库)。假设我的应用程序是由编译器版本A编译的,而我的.so是由编译器版本B编译的,还可以吗?
由于上述原因,不,你不能确定。由于您是库创建者,因此您可以创建 API,以便将库中类型的new内存delete分配/解除分配委托给编译到库中的成员函数,而该成员函数又执行真正的分配/解除分配(如operator new 中所述,运算符new[]
和运算符delete、运算符delete[])。new然后,可以在库和应用程序之间传递和传递指向您类型的对象的指针,并且可以delete在任一侧传递。
这是使用特定于类的分配函数的(不完整)示例:
void* T::operator new(std::size_t count);
以及特定于类的常用释放函数:
void T::operator delete(void* ptr);
它包含foo.hpp并foo.cpp用于使用该库创建libfoo.so(或libfoo.a)程序代码。
foo.hpp
#pragma once
#include <new>
class Foo {
public:
// The "usual" part of your class definition:
Foo(int x);
~Foo();
// This part does NOT get compiled into your library.
// It'll only be used by users of your library:
#ifndef BUILDING_LIB
// Note: operator new and delete are static by default
// single object allocation/deallocation:
void* operator new(std::size_t /* byte_count */) { return Alloc(); }
void operator delete(void* addr) { Free(addr); }
// array allocation/deallocation:
// TODO: operator new[] and delete[]
#endif
private:
int value;
// the functions really doing the memory management
static void* Alloc();
static void Free(void* p);
};
Run Code Online (Sandbox Code Playgroud)
foo.cpp
// Define BUILDING_LIB to disable the proxy operator new/delete functions when building
// the library.
#define BUILDING_LIB
#include "foo.hpp"
#include <cstdlib> // std::aligned_alloc
#include <iostream>
Foo::Foo(int x) : value(x) {
std::cout << "Foo:Foo(" << value << ")\n";
}
Foo::~Foo() {
std::cout << "Foo:~Foo() " << value << "\n";
}
void* Foo::Alloc() {
void* addr = std::aligned_alloc(alignof(Foo), sizeof(Foo));
std::cout << "Alloc() " << sizeof(Foo) << "\t@ " << addr << '\n';
return addr;
}
void Foo::Free(void* addr) {
std::cout << "Free()\t\t@ " << addr << '\n';
std::free(addr);
}
Run Code Online (Sandbox Code Playgroud)
uselib.cpp
#include "foo.hpp"
#include <memory>
int main() {
auto a = std::make_unique<Foo>(123); // heap allocation
// An automatic variable will use the applications memory manager and will not
// use Alloc/Free.
Foo b(456);
}
Run Code Online (Sandbox Code Playgroud)
可能的输出:
Alloc() 4 @ 0x1af7eb0
Foo:Foo(123)
Foo:Foo(456)
Foo:~Foo() 456
Foo:~Foo() 123
Free() @ 0x1af7eb0
Run Code Online (Sandbox Code Playgroud)