GCC C++的最佳内存管理是什么



我的内存管理有什么问题?因为它会导致崩溃,我在下面代码的注释中显示("尝试释放时找不到内存块。"(。我知道我的内存管理不是线程安全的,因为我使用全局变量g_numBlocksg_blocks,在使用多个线程时可能会导致风险。

由于我的内存管理代码似乎太复杂了,有人能建议一个稳定且更好的"C++的内存管理";以避免内存泄漏。

包含错误的代码

#include "emc-memory.h" // <-- Declare the functions MALLOC() and FREE() from other library.
#include <vector>
int main() {
printf("HERE(1)n");
{
std::vector<string> paths = { // <-- Problem, 'std::vector' & 'string' use internal malloc/free & operator new/delete that are overwritten with my own custom memory management.
"/foo/bar.txt",
"/foo/bar.",
"/foo/bar",
"/foo/bar.txt/bar.cc",
"/foo/bar.txt/bar.",
"/foo/bar.txt/bar",
"/foo/.",
"/foo/..",
"/foo/.hidden",
"/foo/..bar",
};
} // <-- It crashes here, error in FREE(): "A memory block could not be found when trying to free.".
printf("HERE(2)n"); // The reason I know it crashes above is this line is not evaluated, only "HERE(1)" is printed. I'm using [RelWithDebInfo] with blurry debugging info.
return 0;
}

编译器:

  • 〔Visual Studio 2015〕〔调试〕:没问题
  • [Visual Studio 2015][RelWithDebInfo]:没问题
  • [GCC 12.1.0 x86_64-w64-mingw32][调试]:没有问题
  • [GCC 12.1.0 x86_64-w64-mingw32][RelWithDebInfo]:损坏,表示存在错误

In";emc存储器.h";在其他库中.so文件

extern const char*  __file;
extern int          __line;
#define new (__file = __FILE__, __line = __LINE__, 0) ? 0 : new
enum MEMORYBLOCKTYPE {
MEMORYBLOCKTYPE_MALLOC,
MEMORYBLOCKTYPE_NEW,
};
void *MALLOC(size_t size, MEMORYBLOCKTYPE type);
void *REALLOC(void *block, size_t newSize);
void  FREE(void *block, MEMORYBLOCKTYPE type);
#define malloc(size)            ((__file = __FILE__, __line = __LINE__, 0) ? 0 : MALLOC(size, MEMORYBLOCKTYPE_MALLOC))
#define realloc(block, newSize) REALLOC(block, newSize)
#define free(block)             FREE(block, MEMORYBLOCKTYPE_MALLOC)

In";emc存储器.cpp";在其他库中.so文件

我在链接中使用此代码来覆盖运算符new&删除:https://codereview.stackexchange.com/questions/7216/custom-operator-new-and-operator-delete

typedef unsigned long long BlockId; // The reason it's 64-bit is a memory block can be freed and reallocated multiple times, which means that there can be a lot of ids.
BlockId g_blockId = 0;
BlockId newBlockId() {
return g_blockId++;
}
struct Block {
const char          *file;
int                  line;
const char          *scope;
char                *hint;
size_t               size;
BlockId              id; // That id is used for comparison because it will never be changed but the block pointer can be changed.
void                *block;
MEMORYBLOCKTYPE      type;
};
bool g_blocks_initialized = false;
int g_numBlocks;
Block **g_blocks;
void *MALLOC(size_t size, MEMORYBLOCKTYPE type) {
if (g_blocks_initialized == false) {
g_blocks_initialized = true;
_initializeList(g_numBlocks, g_blocks);
}
Block *b = (Block *)malloc(sizeof(*b));
b->file  = __file ; __file  = nullptr;
b->line  = __line ; __line  = 0;
b->scope = __scope; __scope = nullptr;
b->hint  = allocateMemoryHint(__hint);
b->size = size;
b->id = newBlockId();
b->block = malloc(size);
b->type = type;
_addListItem(g_numBlocks, g_blocks, b);
return b->block;
}
void FREE(void *block, MEMORYBLOCKTYPE type) {
if (block == nullptr) {
return; // 'free' can free a nullptr.
}
for (int i = 0; i < g_numBlocks; i++) {
Block *b = g_blocks[i];
if (b->block == block) {
if (b->type != type) {
switch (type) {
case MEMORYBLOCKTYPE_MALLOC: EMC_ERROR("The memory block type must be MALLOC."); break;
case MEMORYBLOCKTYPE_NEW:    EMC_ERROR("The memory block type must be NEW.");    break;
default:                     EMC_ERROR("Error");                                 break;
}
}
_removeListItem(g_numBlocks, g_blocks, b);
freeMemoryHint(b->hint); b->hint = nullptr;
SAFE_FREE(b->block);
SAFE_FREE(b);
return;
}
}
EMC_ERROR("A memory block could not be found when trying to free.nnExamples:n - Calling free(pointer) where pointer was not set to zero after it's been called twice, the solution was to use SAFE_FREE(). And if possible, replace any free() with SAFE_FREE(). For example, see Lexer::read0() on the original line "free(out.asIdentifier);".n - If an 'Engine' object is destroyed before destroying a Vulkan object then it can cause this error (It can happen with 'Release' or 'RelWithDebInfo' configuration but not with 'Debug' configuration), that problem happened to me and I stuck there for hours until I realized it.");
}

我谦虚地建议,如果没有明确的理由,GCC C++的最佳内存管理是GCC C++的开箱即用默认内存管理。

这意味着你最好的解决方案是什么都不做,或者现在去掉你对全球运营商的覆盖。

你可能会发现,在系统的某些领域,默认内存管理是次优的,但在2022年,默认选项非常有效,如果你找到了一个更好的通用策略,那就是一篇可发表的论文。

然而,您的问题告诉我们任何关于所讨论的应用程序或您认为您甚至应该尝试更改内存管理的动机的信息,更不用说就应该做什么给出建议了。

当然,您可以添加一个全局分配互斥来阻止内存管理,并使其线程安全。如果这不仅仅是放弃了你希望获得的任何优势,我会感到惊讶。

不确定SAFE_FREE是从哪里来的。如果您在MALLOC函数中看到,它们使用c运行时MALLOC。这意味着如果你想释放这个块,你需要使用相应的free((函数。

确保SAFE_FREE确实使用了带有正确参数的c运行时FREE。