在C / C ++中似乎是常识,在函数完成之前new/malloc
某些内存应该delete/free
的函数,对吗?
但是假设我有这样的问题,有一个函数reader
会将文件中的块读取到缓冲区中,还有另一个函数consumer
将使用这些缓冲区,
void reader(ifstream &ifs)
{
char *buf = new char[100];
ifs.read(buf, 100);
save_buffer(buf); //save this buf into a global array, say buf_array[10]
}
void consumer()
{
for(int i = 0; i < 10; i++)
consume( buf_array[i] ); //do something with those buffers read by reader
}
我的问题是,new
内有许多内存资源reader
,但reader
不能delete
,因为{{1}未使用这些缓冲区}}。 consumer
应该consumer
对这些缓冲区负责吗?
答案 0 :(得分:4)
没有人说分配内存的功能应该释放内存。但通常相同的组件应该处理它。由于您的reader
和consumer
形成一对,因此他们可以将内存协调在一起。
答案 1 :(得分:1)
在C / C ++中似乎是常识,在函数完成之前
new/malloc
某些内存应该delete/free
的函数,对吗?
不,这不一定是真的,你不必在同一个函数中释放内存,只要你在程序结束之前最终释放它。
C ++中可用的一种常见解决方案(但不包括C语言)是在析构函数中释放内存。如果在正确处理复制/移动构造函数和赋值运算符的同时传递包含动态分配的内存的对象,则在调用析构函数时将释放内存。
答案 2 :(得分:1)
原则是“对于每个new
,应该有一个delete
”。这并没有说明两个调用必须在同一个函数内(显然,这不会非常有用)。
您的阅读器分配和消费者释放的示例没有问题。
答案 3 :(得分:1)
您不必在同一个函数中执行new/malloc
(分配)和delete/free
(释放)。只要你的算法保证每个分配都被释放并且只释放一次,这样它就不会导致内存泄漏,那就没问题了。
实际上,分配和释放通常存在于不同的功能中。
记住这些:
1.使用相同的指针进行释放(当然可以传递指针)。如果对指针进行一些算术运算然后使用修改后的指针释放分配,即使指针仍指向分配区域,也会产生错误。
2.如上所述,您应该保证分配已经发布,并且只发布一次。额外的版本会导致错误。
答案 4 :(得分:1)
只要携带指向缓冲区的指针,就不需要在初始化它的同一个函数中释放已分配的缓冲区。
在您的情况下,consumer()
应负责delete
consumer
分配的缓冲区。
至于你的第二个问题,消费者不知道缓冲区的结束位置;你需要以某种方式告诉它。您可以考虑定义一个封装缓冲区及其长度的新struct
,而不是仅仅存储指向缓冲区的指针。这已经完成了:考虑使用std::string
。
答案 5 :(得分:1)
对其他人的答案略有不同:
是的,读者不能在读取功能中释放/删除内存,但我不会让消费者删除内存。在一个简单的情况下工作,但如果您有多个消费者(例如以不同的格式输出)怎么办?如果消费数据具有释放数据的副作用,那么在第一个消费者做到这一点后,你就无法对数据做任何其他事情。
我的阅读器中有一个cleanup()
类型的方法,我明确要求在需要时清理缓冲区。这样,分配内存的模块负责释放它(即使它采用不同的方法)。
e.g。
Data d = Reader.read();
Consumer1.consume(d);
Consumer2.consume(d);
Reader.cleanup(d);
// d is no longer valid.
答案 6 :(得分:1)
您正在将buf的内容复制到实际为消费者提供的全局数组buf_arrray。因此,在上面的例子中,读者可以释放buf。
而且,新的/ mallocs应该释放内存的功能并不是必需的。指针可以传递。最后使用分配的内存的函数需要释放内存。
答案 7 :(得分:0)
您还可以阅读有关共享数组http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/shared_array.htm
的信息使用共享数组,您可以在函数内部分配它们,并通过值将它们传递给其他函数。共享数组保留引用次数的内部计数,并在所有引用超出范围时自动删除内存。
例如
void bar( boost::shared_array< int > );
void foo()
{
boost::shared_array< int > x ( new int[ 100 ] );
bar( x );
// because x has been passed to bar(), its reference count is incremented
// and it will not only be deleted when everyone is finished with it!
// do more things with x
} // the memory held by x is deleted
void bar( boost::shared_array< int > y )
{
// Do things with y here
} // the memory held by y is not deleted here because foo() hasn't yet finished
答案 8 :(得分:0)
按照偏好的降序,您更喜欢:
auto
存储类,因此会自动删除。shared_ptr
等方式共享所有权。3和4几乎并列,但两者都落后于2,这远远落后于1.
在这种情况下,你真正喜欢的是生产者和消费者以上的功能(或类等)的水平,以分配缓冲区,启动生产者和消费者,并在两者完成时删除缓冲区:
class buffer {
std::vector<char> data;
public:
buffer() : data(100) {}
};
process_file(std::string const &name) {
std::vector<buffer> buffers(10);
std::ifstream in(name);
std::pair<std::ifstream *, std::vector<buffer> *> thread_data = {
&in, &buffers
};
prod = start_thread(producer, (void *)&thread_data);
cons = start_thread(consumer);
join(prod);
join(cons);
}
如果你能做到这一点,它可以帮助避免在管理内存时遇到麻烦很多。