Working with stl:list and stl::vector types under interrupt handlers I want to avoid malloc() calls.
The question: What is a best way to prevent malloc() calls in STL list and vector? Is it enough to create structure with predefined size and then avoid push/pop/erase calls?
Thank you in advance
STL containers like std::list
and std::vector
have constructors accepting an Allocator
type. By supplying your own allocator instead of using the default you are able to control how the container allocates memory. This option is rarely used, but using your own allocator in a real time environment is a good example of where this feature is useful (and proves that the designers of STL did a very good job).
The requirements for you custom allocator type is described in 20.1.6 in the C++ standard
It sounds like you want to preallocate memory in your initialization code, so that your interrupt handler can avoid heap allocations. I'll assume that the elements you're storing in these containers do not themselves perform any heap allocations, because that would complicate the answer.
You can preallocate memory for std::vector
by calling the reserve()
method. Methods like push_back()
, pop()
, insert()
, and erase()
manipulate the vector's size (the number of elements it currently contains). They only affect the capacity (the number of elements it has room for) when the new size is larger than the current capacity. reserve(x)
ensures that the capacity is greater or equal to x
, increasing the capacity if necessary. (Also note that the only operation that ever decreases a vector's capacity is swap()
, so you don't have to worry about erase()
reducing the vector's capacity.)
This approach won't work for std::list
, but there's another approach that will: preallocate list elements by inserting them into a "spare" list. Instead of inserting new elements, use the splice()
method to move them from the "spare" list to the "primary" list. Instead of erasing elements, use the splice()
method to move them from the "primary" list to the "spare" list.
As a testimonial: we use two methods mentioned in other answers at my workplace:
Mostly we do these two things to avoid fragmentation, decrease allocator overhead, eliminate the copy-on-grow penalty, etc. But sometimes (especially with eg the instrumenting profiler) we want to absolutely avoid allocation during an interrupt handler.
Usually, however, we avoid issues with interrupts and allocations in other manners:
Note that lock-free data structures could be an alternative to the second bullet here, we haven't set up and done profiling to see if it would help. Designing your own is tricky business anyway.
Paranoia is the better part of valor for interrupt handlers: if you're not certain what you're doing will work, it's sometimes much better to approach the issue in an entirely different manner.
Just one other thing to add: a const std::vector
will not cause allocations. So if your interrupt handling code doesn't change the vector, declare it const
and the compiler will make the vector
stays the same.
As onebyone.livejournal.com mentioned , the C++ standard does not say anything about interrupt handlers. It does talk about signal handlers, but even then it's a very gray area. About the only thing you can do inside a signal handler that's guaranteed to have well-defined behavior across all conforming C/C++ implementations is assigning to a variable of type sig_atomic_t
and returning, eg:
sig_atomic_t flag = 0;
// This signal handler has well-defined behavior
void my_signal_handler(int signum)
{
flag = 1;
}
int main(void)
{
signal(SIGINT, &my_signal_handler);
while(1)
{
doStuff();
if(flag)
{
flag = 0;
actuallyHandleSignalNow();
}
}
return 0;
}
Although in practice, you can almost always get away with doing a little more inside your signal handler.
For std::vector
that should be sufficient. I don't think anything guarantees that though. Memory allocation is considered an implementation detail. If you can restrict yourself to a specific size, I suggest going with a simple static array instead. That way, you have a fine-grained control over what exactly happens.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.