C++多线程内存泄漏问题
C++ multi-thread memory leak issue
一旦以下代码 运行ning,它将占用我所有的内存并导致我的 ARM 64 位处理器出现 OOM 问题。似乎某些 'delete' 操作不起作用...这让我感到困惑。有没有高手帮忙分析下是什么原因? Ttoolchain 还是 libc?
我运行同样的代码在另外两个平台,一个是x64,一个是另一个ARM 32位芯片;他们都很好,除了我的 IPQ ARM 芯片。
环境:
- libc 版本:musl libc 1.1.16
- gcc 版本:5.2.0
- cpu芯片:IPQ ARM 64bit
- os: linux 4.1
#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;
}
- 如果我在头文件线程回调中使用互斥锁,问题就会消失;没有内存泄漏。
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;
}
- 如果我将内存分配大小更改为 1024,则会发生奇怪的事情。 2个线程不会泄漏内存,但是20个线程会导致内存泄漏。无论分配大小如何,只有 1 个线程没有问题。
void *h(void *param)
{
while(1)
{
//char *p = new char[4096];
char *p = new char[1024];
delete[] p;
}
return NULL;
}
- 如果我将
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;
}
- 所以我想如果我重载运算符
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;
}
- 所以我认为内存泄漏可能是由我的运算符
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
一旦以下代码 运行ning,它将占用我所有的内存并导致我的 ARM 64 位处理器出现 OOM 问题。似乎某些 'delete' 操作不起作用...这让我感到困惑。有没有高手帮忙分析下是什么原因? Ttoolchain 还是 libc?
我运行同样的代码在另外两个平台,一个是x64,一个是另一个ARM 32位芯片;他们都很好,除了我的 IPQ ARM 芯片。
环境:
- libc 版本:musl libc 1.1.16
- gcc 版本:5.2.0
- cpu芯片:IPQ ARM 64bit
- os: linux 4.1
#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;
}
- 如果我在头文件线程回调中使用互斥锁,问题就会消失;没有内存泄漏。
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;
}
- 如果我将内存分配大小更改为 1024,则会发生奇怪的事情。 2个线程不会泄漏内存,但是20个线程会导致内存泄漏。无论分配大小如何,只有 1 个线程没有问题。
void *h(void *param)
{
while(1)
{
//char *p = new char[4096];
char *p = new char[1024];
delete[] p;
}
return NULL;
}
- 如果我将
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;
}
- 所以我想如果我重载运算符
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;
}
- 所以我认为内存泄漏可能是由我的运算符
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