I have a struct
that looks like this:
struct queue_item_t {
int id;
int size;
std::string content;
};
I have a std::vector< queue_item_t >
which is populated with many of these from a database query.
When each item is processed, a file is read from disk and its contents put into the content
string member. The item is processed (content
is parsed) and I execute .clear()
on the string so as not to eat up all my memory.
However, this doesn't seem to free the memory. I have hundreds of thousands of items being processed and eventually, the memory usage will rise beyond what's available and the application is killed by Linux with "Out-Of-Memory" as reason.
How do I free the memory used by these strings?
Problem Description. The String::clear() function does only set the length to 0, it does not free the memory. The same for assigning an empty string, as this only checks if the reserved capacity is enough.
While std::string has the size of 24 bytes, it allows strings up to 22 bytes(!!) with no allocation.
As for sizeof(std::string) , typical values on desktop platforms range from 12 to 32 bytes. This is based on a few tests done using Compiler Explorer (link to the test, if you want to test other platforms):
std::string is just a normal class1, so the usual rules apply. If you allocate std::string objects on the stack, as globals, as class members, ... you don't need to do anything special, when they go out of scope their destructor is called, and it takes care of freeing the memory used for the string automatically.
To answer the titular question, the fixed cost of using String is at least 1600 bytes of program space, more if you use more than a few methods. The linker can throw out methods you don't use.
The string object itself is stored on the stack but it points to memory that is on the heap. Why? The language is defined such that the string object is stored on the stack. string's implementation to construct an object uses memory on the heap.
std::string and std::vector do not change container capacity (=> do not release container memory) in clear(). The below trick with temporary object should be used whenever compaction is required (normally it is not required).
my_queue_item.content.clear(); // clear
std::string(my_queue_item.content).swap(my_queue_item.content); // compact
above code can be made simpler when cleanup+compaction are requried:
std::string().swap(my_queue_item.content);
Some string implementations are copy-on-write. Such string, when referred from more than one place, would re-allocate memory on write.
clear
won't free all the memory of the string (probably just the buffer). It will just set the string to an empty one.
If you can call clear
on the string, why not reuse it instead? So, instead of creating a new queue_item_t
, simply replace its string member with the new value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With