C++ DLL 堆内存分配问题
C++ dll heap memory allocation issue
从这个链接中,我知道我们(应用程序(应该始终不要从dll中删除堆内存分配,因为堆内存管理器是不同的。
我有几个问题:
1.(.so文件(Linux(怎么样,情况是一样的吗?
2.( 有没有办法确保应用程序和库(.dll 和 .so(使用相同的堆内存管理器或使用相同的堆内存部分?因此,我们可以分别删除和新建(在 .dll/.so 处新建,在应用程序处删除(。
谢谢。
1.( .so 文件(Linux(怎么样,情况是一样的吗?
是的,使用与最终链接的程序不同的标准C++库实现构建的库可能会以略有不同的方式进行分配。g++
的libstdc++
和clang++
的libc++
是两种不同实现的例子。它们可能是100% ABI 兼容的 - 但第三个未知库可能不是。
2.( 是否有办法确保应用程序和库(.dll 和 .so(使用相同的堆内存管理器或使用相同的堆内存部分?因此,我们可以分别删除和新建(在 .dll/.so 处新建,在应用程序处删除(。
不,编译到库中的内容是库将使用的内容,除非有办法在加载库时初始化库,告诉它使用特定的堆管理器。
请详细解释。我想知道 .so(Linux(,它是否只对应用程序和 .so(库(使用一个堆管理器。假设,我的应用程序由编译器版本 A 编译,而我的 .so 由编译器版本 B 编译,它仍然可以吗?
由于上述原因,不,您无法确定。但是,由于您是库创建者,因此您可以制作 API,以便将库中类型的new
和delete
内存分配/解除分配委托给编译到库中的成员函数,而成员函数又执行实际分配/解除分配(在运算符 new、运算符 new[] 中描述。 和运算符删除,运算符删除[](。然后,可以在库和应用程序之间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);
};
傅.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()tt@ " << addr << 'n';
std::free(addr);
}
使用库.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);
}
可能的输出:
Alloc() 4 @ 0x1af7eb0
Foo:Foo(123)
Foo:Foo(456)
Foo:~Foo() 456
Foo:~Foo() 123
Free() @ 0x1af7eb0
1(符号表在Linux的整个过程中共享。 malloc(( 表示 过程与所有其他部分相同。所以是的,如果流程的所有部分都访问 堆通过 malloc(( et alia 然后它们将共享相同的堆。
2(但是第二个问题我也有点困惑。
堆管理器位于运行时库的静态内存中(Win 的 msvcrXXX 和 Linux 的 crt(。您可以通过两种方式使用运行时库:静态或动态。如果将运行时作为静态链接到自己的库,则无法在库中分配并在另一个库中释放。但是您将运行时链接为动态,然后您可以在库中分配并在另一个库中释放。
库开发人员通过实现自己的方法来释放库内分配的内存来解决这个问题。 例如:
- OpenIPMI调用
ipmi_fru_node_get_field
和ipmi_fru_data_free
。 - CryptoAPI 调用
CertCreateCertificateContext
和CertFreeCertificateContext
- 使用 NTAllocateVirtualMemory 和 GetProcAddress 的内存分配问题不起作用
- C++ DLL 堆内存分配问题
- 单链表分配问题 (nullptr)
- 复制到新阵列时出现动态内存分配问题
- 我不知道为什么会发生堆损坏(关于内存分配问题)
- 如果/else语句未显示/可变分配问题的输出;初学者程序员
- Windows 10中的Char*的内存分配问题
- FMOD EX内存分配问题
- 内存分配问题
- 清除并重新填充 std::vector<std::vector<T>>导致分配问题
- c++析构函数解分配问题
- 结构内存分配问题
- 在 2D 图像阵列中裁剪/插入 - 内存分配问题
- 自定义字符串实现,运算符 + 过载内存分配问题
- C++ 向量分配问题
- 阵列分配问题
- 标准::矢量内存分配问题
- ***glibc检测到***和动态分配问题-C++
- CUDA推力内存分配问题
- 堆损坏/坏分配问题立即在主