gpt4 book ai didi

c++ - 避免由 new(new[]) 引起的内存泄漏

转载 作者:行者123 更新时间:2023-11-28 01:42:29 30 4
gpt4 key购买 nike

我正在开发一个存在内存泄漏的开源库。该库是围绕 boost::asio 构建的数据流服务。服务器端使用堆内存管理系统,该系统提供内存以容纳有限数量的 samples,同时它们等待通过 tcp 连接被推送。首次构建服务器时,会为所有旧的 sample 分配一堆内存。从这个堆中,在 sample 通过套接字传递后,内存返回到堆中。

这很好,除非所有预分配的堆都已被占用。这是创建“示例”的函数:

sample_p new_sample(double timestamp, bool pushthrough) { 
sample *result = pop_freelist();
if (!result){
result = new(new char[sample_size_]) sample(fmt_, num_chans_, this);
}
return sample_p(result);
}

sample_p 只是一个模板化为 sample 类的 typedef 智能指针。

违规行在中间。当 freelist 上没有内存块时,我们需要创建一些。这会泄漏内存。

我的问题是为什么会这样?由于我将新样本插入智能指针,当它超出范围时不应该释放内存吗(稍后它会从堆栈中弹出。)?我是否需要以某种方式处理内部分配的内存——即new char[sample_size_]分配的内存?如果是,我该怎么做?

编辑:@RichardHodges 这里是一个可编译的 MCVE。这是高度简化的,但我认为它准确地捕捉到了我在原始代码中面临的问题。

#include <boost/intrusive_ptr.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <iostream>

typedef boost::intrusive_ptr<class sample> sample_p;
typedef boost::lockfree::spsc_queue<sample_p> buffer;
class sample {

public:
double data;
class factory{
public:
friend class sample;
sample_p new_sample(int size, double data) {
sample* result = new(new char[size]) sample(data);
return sample_p(result);
}
};

sample(double d) {
data = d;
}

void operator delete(void *x) {
delete[](char*)x;
}

/// Increment ref count.
friend void intrusive_ptr_add_ref(sample *s) {

}

/// Decrement ref count and reclaim if unreferenced.
friend void intrusive_ptr_release(sample *s) {

}

};


void push_sample(buffer &buff, const sample_p &samp) {

while (!buff.push(samp)) {
sample_p dummy;
buff.pop(dummy);
}
}

int main(void){
buffer buff(1);
sample::factory factory_;
for (int i = 0; i < 10; i++)
push_sample(buff, factory_.new_sample(100,0.0));
std::cout << "press any key to exit" << std::endl;
char foo;
std::cin >> foo;

return 0;
}

当我单步执行代码时,我注意到我的删除运算符从未在样本指针上被调用。我猜想我正在开发的库(同样,我没有编写,所以我仍在学习它的方法)误用了 intrusive_ptr 类型。

最佳答案

您正在使用 new[] 分配内存,因此您需要使用 delete[] 释放它(在 char* 上)。智能指针可能默认调用 delete,因此您应该提供一个调用 delete[] 的自定义删除器(在手动调用 sample 的析构函数之后) >).这是一个使用 std::shared_ptr 的例子.

auto s = std::shared_ptr<sample>(
new (new char[sizeof(sample)]) sample,
[](sample* p) {
p->~sample();
delete[] reinterpret_cast<char*>(p);
}
);

但是,当您的缓冲区仅包含一个对象时,为什么要使用放置 new 呢?为什么不直接使用常规 new 呢?

auto s = std::shared_ptr<sample>(new sample);

或者更好(使用 std::shared_ptr),使用工厂函数。

auto s = std::make_shared<sample>();

关于c++ - 避免由 new(new[]) 引起的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46607395/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com