C++多线程内存泄漏问题

C++ multi-thread memory leak issue

一旦以下代码 运行ning,它将占用我所有的内存并导致我的 ARM 64 位处理器出现 OOM 问题。似乎某些 'delete' 操作不起作用...这让我感到困惑。有没有高手帮忙分析下是什么原因? Ttoolchain 还是 libc?

我运行同样的代码在另外两个平台,一个是x64,一个是另一个ARM 32位芯片;他们都很好,除了我的 IPQ ARM 芯片。

环境:

#include <iostream>
#include <cstring>
#include <list>
#include <memory>
#include <pthread.h>


void *h(void *param)
{
    while(1)
    {
        char *p = new char[4096];
        delete[] p;
    }
    return NULL;
}


int main(int argc, char *argv)
{
    pthread_t th[50];
    int thread_cnt = 2;
    for(int i = 0; i < thread_cnt; i++) 
        pthread_create(th+i, NULL, h, NULL);
        
    for(int i = 0; i < thread_cnt; i++) 
        pthread_join(th+i, NULL);

    return 0;
}
  1. 如果我在头文件线程回调中使用互斥锁,问题就会消失;没有内存泄漏。
std::mutex thlock;
void *h(void *param)
{
    while(1)
    {
        std::lock_guard<std::mutex> lk(thlock);
        char *p = new char[4096];
        delete[] p;
    }
    return NULL;
}

  1. 如果我将内存分配大小更改为 1024,则会发生奇怪的事情。 2个线程不会泄漏内存,但是20个线程会导致内存泄漏。无论分配大小如何,只有 1 个线程没有问题。
void *h(void *param)
{
    while(1)
    {
        //char *p = new char[4096];
        char *p = new char[1024];
        delete[] p;
    }
    return NULL;
}

  1. 如果我将new/delete替换为std::malloc/std::free,问题就会消失;没有内存泄漏。
void *h(void *param)
{
    while(1)
    {
        //char *p = new char[4096];
        char *p = (char *)std::malloc(4096);
        std::free(p);
        //delete[] p;
    }
    return NULL;
}

  1. 所以我想如果我重载运算符 new/delete 和我的“new/delete”通过使用 std::malloc/[= 分配内存25=],也许问题可以解决。但 奇怪的事情又发生了;内存泄漏仍然存在。
void* operator new(std::size_t sz) // no inline, required by [replacement.functions]/3
{
    std::printf("global op new called, size = %zu\n", sz);
    if (sz == 0)
        ++sz; // avoid std::malloc(0) which may return nullptr on success
 
    if (void *ptr = std::malloc(sz))
        return ptr;
 
    throw std::bad_alloc{}; // required by [new.delete.single]/3
}
void operator delete(void* ptr) noexcept
{
    std::puts("global op delete called");
    std::free(ptr);
}

void *h(void *param)
{
    while(1)
    {
        char *p = new char[4096];
        delete[] p;
    }
    return NULL;
}

  1. 所以我认为内存泄漏可能是由我的运算符 new/delete 而不是 malloc/free 引起的,所以我将代码更改为下面显示的是什么。我并没有真正调用 malloc/free 而是 return 一个预分配的缓冲区。但是内存泄漏问题消失了,所以问题似乎不仅来自 new/delete...
char pp[4096];
void* operator new(std::size_t sz) // no inline, required by [replacement.functions]/3
{
    std::printf("global op new called, size = %zu\n", sz);
    if (sz == 0)
        ++sz; // avoid std::malloc(0) which may return nullptr on success
 
    return (void *)pp;
    //if (void *ptr = std::malloc(sz))
        //return ptr;
 
    throw std::bad_alloc{}; // required by [new.delete.single]/3
}
void operator delete(void* ptr) noexcept
{
    std::puts("global op delete called");
    //std::free(ptr);
}

所以,发生了什么事?有没有高手给我出出主意?我想这可能导致了 musl libc thread lib;似乎线程同步无法正常工作...或者是否有补丁已经解决了这个问题?

此问题涉及 musl libc,并已通过以下补丁修复。

https://git.musl-libc.org/cgit/musl/commit/src/malloc?id=3e16313f8fe2ed143ae0267fd79d63014c24779f

以上补丁涉及 realloc 的 buffur 溢出问题,已被以下 2 个补丁修复:

https://git.musl-libc.org/cgit/musl/commit/src/malloc?id=cb5babdc8d624a3e3e7bea0b4e28a677a2f2fc46 https://git.musl-libc.org/cgit/musl/commit/src/malloc?id=fca7428c096066482d8c3f52450810288e27515c