阅读一些Apple代码,我偶然发现了以下C块
alloca(sizeof(CMTimeRange) * 3)
与分配堆栈内存通过
相同 CMTimeRange *p = CMTimeRange[3]
?
对性能有任何影响吗?是否需要释放记忆?
答案 0 :(得分:0)
假设Joachim指出你的意思是CMTimeRange someVariableName[3]
......
两者都会在堆栈上分配内存。
我猜alloca()
必须在你的函数序言之后添加额外的代码来进行分配...函数序言是编译器自动生成的代码,用于在堆栈上创建空间。结果是你的函数在编译后可能会略大一些,但不是很多......一些额外的指令来修改堆栈指针和可能的堆栈帧。我想编译器可以优化调用,如果它不在条件分支中,或者甚至将它提升到条件分支之外呢?
我在没有优化的情况下对我的MQX编译器进行了实验......它不是客观的,只是C,也是一个不同的平台,但希望这是一个足够好的近似并且确实显示了发出的代码的差异。我在堆栈上使用了两个带有大数组的简单函数,以确保必须使用堆栈空间(变量不能仅存在于寄存器中)。
显然不建议将大型数组放在堆栈上......这仅用于演示目的。
unsigned int TEST1(unsigned int stuff)
{
unsigned int a1[100]; // Make sure it must go on stack
unsigned int a2[100]; // Make sure it must go on stack
a1[0] = 0xdead;
a2[0] = stuff + 10;
return a2[0];
}
unsigned int TEST2(unsigned int stuff)
{
unsigned int a1[100]; // Make sure it must go on stack
unsigned int *a2 = alloca(sizeof(unsigned int)*100);
a1[0] = 0xdead;
a2[0] = stuff + 10;
return a2[0];
}
生成了以下汇编程序:
<强> TEST1:强>
数组a1
和a2
都放在函数序言中的堆栈中......
0: 1cfcb6c8 push %fp
4: 230a3700 mov %fp,%sp
8: 24993901 sub3 %sp,%sp,100 # Both arrays put on stack
c: 7108 mov_s %r1,%r0
e: 1b38bf98 0000dead st 0xdead,[%fp,0xffff_fce0] ; 0xdead
16: e00a add_s %r0,%r0,10
18: 1b9cb018 st %r0,[%fp,0xffff_fe70]
1c: 240a36c0 mov %sp,%fp
20: 1404341b pop %fp
24: 7ee0 j_s [%blink]
<强> TEST2:强>
只有数组a1
放在proglogue的堆栈中...必须生成额外的代码行来处理alloca
。
0: 1cfcb6c8 push %fp
4: 230a3700 mov %fp,%sp
8: 24593c9c sub3 %sp,%sp,50 # Only one array put on stack
c: 240a07c0 mov %r4,%blink
10: 220a0000 mov %r2,%r0
14: 218a0406 mov %r1,0x190 # Extra for alloca()
18: 2402305c sub %sp,%sp,%r1 # Extra for alloca()
1c: 08020000r bl _stkchk # Extra for alloca()
20: 738b mov_s %r3,%sp # Extra, r3 to access write via pointer
22: 1b9cbf98 0000dead st 0xdead,[%fp,0xffff_fe70] ; 0xdead
2a: 22400280 add %r0,%r2,10
2e: a300 st_s %r0,[%r3] # r3 to access write via pointer
30: 270a3100 mov %blink,%r4
34: 240a36c0 mov %sp,%fp
38: 1404341b pop %fp
3c: 7ee0 j_s [%blink]
此外,您将通过指针访问alloca()
内存(除非有明确的编译器优化...我不知道)因此导致实际的内存访问。自动变量可能被优化为仅仅是寄存器访问,这更好......编译器可以使用寄存器着色来确定自动变量最好留在寄存器中以及它们是否需要在堆栈中。
我快速搜索了C99标准(C11是关于......我的参考文献已经过时了)。无法看到对alloca
的引用,因此可能不是标准定义的函数。可能的缺点?
答案 1 :(得分:0)
如果你真的只想在堆栈中分配某些东西的3
元素,那么使用alloca
根本就没有意义。只有在运行时依赖于某个动态参数的变量长度,或者在同一函数中执行未知数量的此类分配时才有意义。
alloca
不是标准功能,因平台而异。 C标准更倾向于引入VLA,可变长度阵列作为替代品。
答案 2 :(得分:0)
这与分配堆栈内存相同[...]
我觉得不太好。声明局部变量会导致在输入堆栈帧时保留内存(通过从堆栈指针中减去变量的大小并调整对齐)。
看起来像alloca(3)通过在遇到它时调整堆栈指针来工作。请注意手册页的“错误”部分。
alloca()依赖于机器和编译器; 不鼓励使用它。
alloca()稍微不安全,因为它无法确保返回的指针指向有效且可用的内存块。所做的分配可能会超出堆栈的范围,甚至可能会进一步进入内存中的其他对象,而alloca()无法确定这样的错误。避免使用大量无界分配的alloca()。
这两点在我看来总结如下:
请勿使用ALLOCA