在我的代码中,我在 lambda 中创建了一个 shared_ptr
,以便将 PNG 文件保存为后台任务。不幸的是,即使我有一个用于 shared_ptr
的自定义删除器,似乎字节没有正确释放。
我用来创建 shared_ptr
的代码:
std::shared_ptr<GLubyte> buffer = std::shared_ptr<GLubyte>((GLubyte*) malloc(*dataLength), [](GLubyte* buffer) {
free(buffer);
});
为了保存文件并最终释放它:
std::thread t([=, buffer = std::move(buffer)]() mutable {
bool done = writePNGFileFromBuffer(path, buffer.get(), width, height);
return done;
});
t.detach();
我尝试将 buffer.reset()
放入 lambda 中,但尽管缓冲区为空,但内存未被释放。我还尝试将创建者功能更改为类似以下内容:
std::shared_ptr<GLubyte> buffer = std::shared_ptr<GLubyte>((GLubyte*) malloc(*dataLength), std::free);
但它也不起作用。现在我一直在使用 lambda 删除器,因为那时我可以尝试在其中放置一个断点并检查是否调用了 free
,但内存仍然没有释放。
此外,如果我将 free(buffer.get())
放入 lambda 中,我已经验证了该版本有效,但对我来说放置它没有任何意义,因为我正在使用 shared_ptr
为了避免这样的事情。
你能帮我释放这个缓冲区吗?非常感谢。
最佳答案
我编写了这个小测试工具来证明新/删除正在正确执行。
注意缓冲区构造函数中 new/delete[] 的使用。您对 malloc/free 的使用给代码带来了难闻的气味。求助于 free(ptr.get()) 隐藏了一些您尚未解决的其他逻辑问题。如果你把它留在程序中,它稍后会咬你。
proxy
替代了计算分配和销毁数量的 GLubyte,因此我可以使用 assert
确认每个构造都有相应的销毁。
#include <iostream>
#include <memory>
#include <thread>
#include <cassert>
#include <atomic>
using namespace std;
#define USE_PROXY 1
struct proxy
{
proxy() {
++_count;
}
~proxy() {
--_count;
}
static std::atomic<size_t> _count;
};
std::atomic<size_t> proxy::_count = { 0 };
#if USE_PROXY
using GLubyte = proxy;
#else
//using GLubyte = uint8_t;
#endif
bool writePNGFileFromBuffer(const char* path, const GLubyte* bytes, int width, int height)
{
return true;
}
auto main() -> int
{
{
int dataLength = 10000;
auto buffer = std::shared_ptr<GLubyte>(new GLubyte[dataLength],
[](GLubyte* p) { delete[] p; });
const char* path = "/tmp/foo";
int width = 100, height = 100;
std::thread t([=, buffer = std::move(buffer)]() mutable {
bool done = writePNGFileFromBuffer(path, buffer.get(), width, height);
return done;
});
t.join();
assert(!buffer);
}
assert(proxy::_count == 0);
return 0;
}
进一步思考,您可能想知道如何处理 write....
函数中的失败情况。目前返回值被丢弃。有几种方法可以解决这个问题——一种是提供一个 lambda,可以在写操作完成时调用它。另一种是将写操作包装到 std::async 中。
bool writeSharedPNGFileFromBuffer(const char* path, shared_ptr<const GLubyte> bytes, int width, int height)
{
return writePNGFileFromBuffer(path, bytes.get(), width, height);
}
auto main() -> int
{
{
int dataLength = 100;
auto buffer = std::shared_ptr<GLubyte>(new GLubyte[10000], [](GLubyte* p) { delete[] p; });
const char* path = "/tmp/foo";
int width = 100, height = 100;
auto f = std::async(launch::async, writeSharedPNGFileFromBuffer, path, move(buffer), width, height);
// f is a std::future - a handle to somewhere the result will eventually land.
// perform main thread work here...
// ... and get the return value when we're ready to deal with it
auto written = f.get();
cout << "written: " << written << endl;
assert(!buffer);
}
assert(proxy::_count == 0);
return 0;
}
关于c++ - shared_ptr 未在线程中释放自定义 malloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31200796/