我的代码正在分配内存并且从不释放它,即使它应该(至少在我看来)。
标题看起来像这样:
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
}
所以当我打电话时对象.functionOne(),内存被分配给对象.ioService_对象,以便能够调用绑定的异步方法。然后在循环之后,接受器上所有挂起的异步操作都将被取消。一旦出现以下情况,就会调用适当的处理程序Object.ioService_.run()被称为(我一直在测试)。但由于某种原因,分配的内存没有被释放。那么有人可以解释一下为什么内存没有被释放并给我一个提示如何释放它吗?
顺便说一句:我正在 Debian 上工作并正在研究/proc/自我/状态 -> VmRSS查看已使用的内存。
@维尼·法尔科
#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 循环中的限制,您将观察到程序保留了大量内存,即使在调用所有异步处理程序后应该释放它。但是SSL套接字对象没有被释放,这就是我的问题:为什么内存(特别是为 sslSocket 分配的内存)绑定到函子功能二,即使在异步方法之后也不会释放功能二已被调用并且没有引用SSL套接字离开了?
我解释我的担忧的最后方法(4 月 28 日编辑)
好吧,我做了一个可运行的例子,这表明了我的担忧:我的问题在一个例子中 http://melpon.org/wandbox/permlink/S56tYueJySIHdsWO
Output:
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,这可能会让您感到困惑,但我的问题不是我的示例中是否以及在何处发生内存泄漏。这是关于内存分配与io服务目的。首先我认为,所声称的内存正在无限增加。我采用了最后一种方法来理解这种行为,并得出结论:内存管理没有问题。操作系统不会回收内存,但程序的内存分配会收敛到一个限制,这对我来说没问题。所以这个问题不适合我。
示例:聚合内存消耗 http://melpon.org/wandbox/permlink/i5k59o38K8azDX2o
最让我不安的是我的本地实现表现出略有不同的行为。在那里,内存被操作系统回收,当io服务对象已完成其工作并重置,这满足了我的期望。
总结一下所有的观察结果:
分配的内存由 C++ 运行时和操作系统管理。直接观察分配过程是相当困难的(如果不是不可能的话?),因为它经过优化以减少对新内存页面的请求量,这意味着分配和freed操作系统可能不会立即重新分配内存。
为了向我指出这种行为的关键点,我想描述我的程序的用法:我正在开发一个服务器应用程序,这意味着该程序应该运行无限的时间。如果程序在某个时间声明了大量的峰值内存,那完全没问题,但它需要在运行时的某个时刻释放声明的内存,而不是在运行时之后。所以对我来说,只剩下一个问题:
操作系统会在某个时候回收已声明(但未使用)的内存吗?或者我必须自己管理内存(用new and delete)在运行时?