My code is allocating memory and never freeing it, even though it should (at least in my opinion).
The header looks like this:
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)
}
And my source like this:
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
}
So when i call Object.functionOne(), memory is getting allocated to the Object.ioService_ object, in order to be able to call the bound asynchronous method. Then after the loop, all pending asynchronous actions on the acceptor are getting canceled. The appropriate handler is getting invoked as soon as Object.ioService_.run() is called (i've been testing that). BUT for some reason, the allocated memory does not get freed. So can someone please explain, why the memory is not getting deallocated and give me a hint how to free it?
Btw.: I'm working on debian and looking at /proc/self/status -> VmRSS to whatch the used memory.
@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;
}
}
My question is not, if and why the destructor of T is called, this works as supposed to. But the behaviour concerning the used memory is strange. So if you increase the limit in the for loop, you will observe, that a lot of memory is getting reserved by the program, even though it should be released after all asnchronous handlers have been invoked. But the sslSocket objects are not getting deallocated, which is what my question is about: Why is the memory (specifically the memory allocated for the sslSocket), bound to the functor functionTwo, not deallocated, even after the asynchronous method fucntionTwo has been invoked and no reference to the sslSocket is left?
My final approach to explain my concern (edit 28 April)
Alright, i made a runnable example, that shows my concern: My Problem in an example
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
What's even more crazy is, that in my own local implementation I get the following output:
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
So it can clearly be seen: the memory is not freed, even after all asynchronous operations have been invoked.
Summary and understood(?) behaviour (last edit)
As some of you might have missunderstood, i'm not thinking that there is some kind of a leak in my code. I named the structure in my code example Leak, which might have confused you, but my question is not if and where a memory leak occurs in my example. It's about the memory allocation in combination with the ioService object. First I thought, that the claimed memory is increasing infinitly. I made a last approach to understand this behaviour and came to the conclusion, that the memory management is fine. Memory is not reclaimed by the OS, but the program's memory allocation is converging to a limit, which is fine with me. So this problem is out of my way.
Example: Converging memory consumption
What disturbed me most was that my local implemention showed a slightly different behaviour. There the memory was reclaimed by the OS, when the ioService object was done with its jobs and reset, which satisfied my expectations.
So to sum up all observations:
The allocated memory is managed by the C++ Runtime and the OS. It's quite difficult (if not even impossible?) to directly observe the allocation procedure, since it's optimized to reduce the amount of requests for new memory pages, which means that allocated and freed memory might not be immidiatly reallocated by the OS.
To point out the critical point to me with this behaviour, i want to describe the usage of my program: I'm developing a server application, which means, that the program should run an infinit amount of time. If the program claims a lot of peak memory at some time, it's totaly fine, but it needs to release the claimed memory at some point in runtime, not after the runtime. So to me, there is only one question remaining:
Will the claimed (but unused) memory be reclaimed by the OS at some time? Or do I have to manage the memory on my own (with new and delete) in runtime?