在中断处理程序下使用stl:list和stl :: vector类型我想避免malloc()调用。
问题:在STL列表和向量中阻止malloc()调用的最佳方法是什么?是否足以创建具有预定义大小的结构,然后避免推/弹/擦除调用?
提前谢谢
答案 0 :(得分:14)
std::list
和std::vector
等STL容器的构造函数接受Allocator
类型。通过提供自己的分配器而不是使用默认值,您可以控制容器分配内存的方式。很少使用此选项,但在实时环境中使用您自己的分配器是此功能有用的一个很好的示例(并证明STL的设计人员做得非常好)。
自定义分配器类型的要求在C++ standard
中的20.1.6中描述答案 1 :(得分:7)
听起来你想在初始化代码中预先分配内存,这样你的中断处理程序就可以避免堆分配。我假设您存储在这些容器中的元素本身不会执行任何堆分配,因为这会使答案复杂化。
您可以通过调用std::vector
方法为reserve()
预分配内存。像push_back()
,pop()
,insert()
和erase()
这样的方法会操纵向量的大小(当前包含的元素数)。当新尺寸大于当前容量时,它们仅影响容量(它有空间的元件数量)。 reserve(x)
确保容量大于或等于x
,必要时增加容量。 (另请注意,唯一降低向量容量的操作是swap()
,因此您不必担心erase()
会降低向量的容量。)
这种方法不适用于std::list
,但还有另一种方法:通过将列表元素插入“备用”列表来预分配列表元素。使用splice()
方法将它们从“备用”列表移动到“主要”列表,而不是插入新元素。不使用擦除元素,而是使用splice()
方法将它们从“主”列表移动到“备用”列表。
答案 2 :(得分:4)
作为推荐:我们在工作场所使用其他答案中提到的两种方法:
大多数情况下,我们会做这两件事以避免碎片,减少分配器开销,消除复制增加的惩罚等。但有时(特别是对于仪表分析器)我们希望在中断处理程序期间绝对避免分配。 / p>
但是,通常我们会以其他方式避免中断和分配问题:
请注意,无锁数据结构可以替代此处的第二个项目符号,我们尚未设置和完成概要分析以查看它是否有帮助。无论如何,设计自己的东西都很棘手。
对于中断处理程序来说,偏执狂是勇敢的一部分:如果你不确定你正在做什么会起作用,有时以完全不同的方式处理问题要好得多。
答案 3 :(得分:3)
要添加的另一件事:const std::vector
不会导致分配。因此,如果您的中断处理代码没有更改向量,请将其声明为const
,编译器将使vector
保持不变。
答案 4 :(得分:2)
作为onebyone.livejournal.com mentioned,C ++标准没有提及任何关于中断处理程序的内容。它确实讨论了信号处理程序,但即使这样,它也是一个非常灰色的区域。关于在信号处理程序中唯一能够保证在所有符合要求的C / C ++实现中具有良好定义的行为的事情是分配给sig_atomic_t
类型的变量并返回,例如:
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;
}
虽然在实践中,你几乎总能在信号处理程序中做更多的事情。
答案 5 :(得分:1)
对于std::vector
来说应该足够了。尽管如此,我认为没有任何保证。内存分配被视为实现细节。如果您可以将自己限制为特定大小,我建议使用简单的静态数组。这样,您可以对实际发生的情况进行细粒度控制。