我的代码在分配内存后从未释放它,尽管我认为应该释放。
头文件如下:
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket_t;
class Object {
boost::asio::io_service ioService_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ssl::context context_;
void functionOne();
void functionTwo(shared_ptr<sslSocket_t>& sslSocket, const boost::system::error_code& error)
}
我的源代码如下:
void Object::functionOne() {
for (int i = 0; i < 10; i++) {
shared_ptr<sslSocket_t> sslSocket(new sslSocket_t(ioService_, context_));
acceptor_.async_accept(sslSocket->lowest_layer(),
boost::bind(&Object::functionTwo, this, sslSocket, boost::asio::placeholders::error));
}
acceptor_.cancel();
boost::asio::io_service::work work(ioService_);
ioService_.run();
}
void functionTwo(shared_ptr<sslSocket_t>& sslSocket, const boost::system::error_code& err) {
// Do nothing
}
当我调用Object.functionOne()时,内存被分配给Object.ioService_对象,以便能够调用绑定的异步方法。然后在循环之后,所有挂起的异步操作都将被取消。只要调用Object.ioService_.run(),适当的处理程序就会被调用(我一直在测试)。但出于某种原因,分配的内存没有被释放。所以有人能解释一下,为什么内存没有被释放,并给我一个提示如何释放它吗?
顺便说一下:我正在debian上工作,并查看/proc/self/status -> VmRSS以观察使用的内存。
@Vinnie Falco
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <memory>
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket_t;
using namespace std;
struct T {
boost::asio::io_service ioService_;
boost::asio::ip::tcp::acceptor acceptor_;
boost::asio::ssl::context context_;
void functionOne() {
for (int i = 0; i < 10; i++) {
shared_ptr<sslSocket_t> sslSocket(new sslSocket_t(ioService_, context_));
acceptor_.async_accept(sslSocket->lowest_layer(),
boost::bind(&T::functionTwo, this, sslSocket, boost::asio::placeholders::error));
}
acceptor_.cancel();
boost::asio::io_service::work work(ioService_);
ioService_.run();
}
void functionTwo(shared_ptr<sslSocket_t>& sslSocket, const boost::system::error_code& err) {
// Do nothing
}
T() : acceptor_(ioService_,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 443)),
context_(boost::asio::ssl::context::sslv23_server) {
}
~T() {
}
};
int main() {
try {
T t;
t.functionOne();
} catch (std::exception& e) {
cout << "Exception: " << e.what() << endl;
}
}
我的问题不是关于T的析构函数是否被调用,也不是为什么它被调用,这个已经能够正常工作了。但是我们有点奇怪的现象,具体涉及到内存的使用。
如果你增加for循环的限制条件,你会观察到程序会使用大量的内存,即使在所有异步处理程序调用后应该释放了所有内存。但是sslSocket对象没有被解除分配,这就是我的问题所在:为什么与functionTwo相关联的内存(特别是为sslSocket分配的内存)在异步方法functionTwo被调用后,没有被释放,而且不再存在任何对sslSocket的引用?
我最终解释我的疑虑(编辑4月28日)
好吧,我创建了一个可运行的示例来展示我的问题: My Problem in an example
输出:
Before leaking call: 6984 kB
Asynchronous calls of functionTwo: 10000
Memory while ioService is still running: 460244 kB
Memory after ioService is stopped: 460244 kB
更疯狂的是,在我自己的本地实现中,我得到了以下输出:
Memory leaking call: 8352 kB
Asynchronous calls of functionTwo: 10000
Memory while ioService is still running: 471932 kB
Memory after ioService is stopped: 8436 kB
因此可以清楚地看到:即使在调用了所有异步操作之后,内存也没有被释放。
总结和理解的行为(最后编辑)
正如你们中的一些人可能误解了一样,我并不认为我的代码中存在泄漏。我在代码示例中命名了结构为Leak,这可能会让你们感到困惑,但我的问题不是在我的示例中是否发生了内存泄漏,而是关于内存分配与ioService对象的组合。起初,我认为所声称的内存无限增加。我最后尝试了解决这个问题,并得出结论,内存管理是好的。内存没有被操作系统回收,但程序的内存分配正在收敛到一个极限,这对我来说很好。所以这个问题已经解决了。 示例:收敛内存消耗 最让我困扰的是,我的本地实现显示了略微不同的行为。当ioService对象完成其工作并重置时,操作系统会回收内存,这符合我的预期。
总结所有观察结果:
分配的内存由C++运行时和操作系统管理。直接观察分配过程相当困难(甚至不可能?),因为它被优化以减少对新内存页的请求次数,这意味着分配和释放的内存可能不会立即被操作系统重新分配。
为了向我指出这种行为的关键点,我想描述一下我的程序的用途:我正在开发一个服务器应用程序,这意味着程序应该无限运行。如果程序在某个时候声称需要大量峰值内存,那么完全没有问题,但它需要在运行时的某个时刻释放所需内存,而不是在运行后。对我来说,只剩下一个问题:
未使用的已声称内存是否会在某个时候被操作系统回收?还是我需要在运行时自己管理内存(使用new和delete)?