PC何时在if块内部分配静态char*
When does PC allocate static char* inside of if block
如果我有
if (a)
{
char a[10000]=AllElementsFromBufferA();
DoSomethingWithA(a);
}
else if (b)
{
char b[10000]=AllElementsFromBufferB();
DoSOmethingWithB(b);
}
else if (c)
{
.
.
.
x 70;
PC何时分配?即使它不去这里,也会分配它吗?由于我的代码具有许多IF-S,SELE-S和性能非常重要,因此我不知道我是否应该动态分配或喜欢这样。因为,如果这也耗尽了太多的记忆,那也很糟糕。
谢谢!
编辑1 我放了一些更现实的例子
我所知道的编译器将为所有块范围变量分配空间输入处的所有块变量,无论是否被拿到分支,至少对于小变量(标量,小数组等))。在大多数平台上,搁置堆栈空间只是调整堆栈指针的问题,这是一个相当便宜的操作。此外,我认为除了当地人的空间外,还要搁置一些"划痕"空间的ABIS任务。
我写了以下示例:
#include <stdio.h>
int main( void )
{
int foo = 0;
scanf( "%d", &foo );
if ( foo == 1 )
{
char a[10000] = "foo";
printf( "a = %sn", a );
}
else if ( foo == 2 )
{
char b[10000] = "bar";
printf( "b = %sn", b );
}
else
{
char c[10000] = "bletch";
printf( "c = %sn", c );
}
printf( "donen" );
return 0;
}
并与GCC(5.3.0,mingw)一起编译如下:
gcc -S alloc.c
给我以下机器代码列表:
.file "alloc.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "%d "
LC1:
.ascii "a = %s12 "
LC2:
.ascii "b = %s12 "
LC3:
.ascii "c = %s12 "
LC4:
.ascii "done "
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB10:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
movl $10032, %eax // allocate stack space
call ___chkstk_ms // with these three
subl %eax, %esp // instructions
call ___main
movl $0, 10028(%esp)
leal 10028(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _scanf
movl 10028(%esp), %eax
cmpl $1, %eax // if ( foo == 1 )
jne L2
movl $7303014, 28(%esp) // a[] = "foo"
leal 32(%esp), %eax
movl $9996, %edx
movl %edx, 8(%esp)
movl $0, 4(%esp)
movl %eax, (%esp)
call _memset
leal 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
jmp L3
L2:
movl 10028(%esp), %eax
cmpl $2, %eax // else if ( foo == 2 )
jne L4
movl $7496034, 28(%esp) // b[] = "bar"
leal 32(%esp), %eax
movl $9996, %edx
movl %edx, 8(%esp)
movl $0, 4(%esp)
movl %eax, (%esp)
call _memset
leal 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC2, (%esp)
call _printf
jmp L3
L4: // else
movl $1952803938, 28(%esp) // c[] = "bletch"
movl $26723, 32(%esp)
leal 36(%esp), %eax
movl $9992, %edx
movl %edx, 8(%esp)
movl $0, 4(%esp)
movl %eax, (%esp)
call _memset
leal 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC3, (%esp)
call _printf
L3:
movl $LC4, (%esp)
call _puts
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE10:
.ident "GCC: (GNU) 5.3.0"
.def _scanf; .scl 2; .type 32; .endef
.def _memset; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef
.def _puts; .scl 2; .type 32; .endef
所以,海湾合作委员会在这里做了相当聪明的事情。首先,它能够确定您在任何给定时间都只能使a
或b
或c
中的一个之一活跃,因此它并没有尝试为所有这三个分配空间。相反,它为一个实例分配了足够的空间,还有一些划痕空间:
movl $10032, %eax
call ___chkstk_ms
subl %eax, %esp
我假设__chkstk_ms
确定是否有足够的堆栈空间适合该请求,如果没有,则会引发异常。
除非采用该特定分支,否则它不会尝试初始化每个实例:
movl $7303014, 28(%esp) // a[] = "foo"
movl $7496034, 28(%esp) // b[] = "bar"
movl $1952803938, 28(%esp) // c[] = "bletch"
movl $26723, 32(%esp)
不用为字符串文字拨出空间"foo"
,"bar"
和"bletch"
,而是使用movw
和movl
指令复制2个和4字节的整数,其位模式与这些字符串的ASCII字符序列相对应。IOW:
7303014 = 0x006f6f66 == " oof"
7496034 = 0x00726162 == " rab"
1952803938 = 0x74656c62 == "telb"
26723 = 0x00006863 == " hc"
请记住,X86是小末日,所以所有内容都呈"向后"。
重要
这是一个一个 compiler 一个一个平台的行为 - 没有理由相信不同的编译器会以相同的方式行事。但是,我的经验使我认为大多数编译器都会尝试对分配空间的分配方式,尤其是对于非常大的物体而言。
相关文章:
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 以下代码执行哪种内存分配(动态或静态)?
- 将 RTOS 队列对象封装在仅具有静态分配的 IQueue 自定义接口中
- 如何静态识别动态堆分配?
- 如何为静态常量模板化专用整数值分配存储
- 静态分配对象的值初始化
- (为什么)我们可以在初始化中将非静态类成员分配给静态变量吗?
- 将基类分配给派生对象,反之亦然,以C++以及静态和动态对象之间的差异
- 将静态字符数组中的字符分配给动态分配的字符数组 - 访问冲突
- 动态分配的数组和静态数组之间的区别
- 将本地 OpenCV Mat 变量声明为静态以防止重新分配
- 对静态分配的子类对象进行静态分配的纯虚拟父类引用是否合法?
- C++编译时使用 constexpr 字符数组指针分配静态数组?
- 使用 MapViewOfFile 分配静态共享内存
- PC何时在if块内部分配静态char*
- GCC如何分配静态运行的数组长度
- 我正在尝试在类中动态分配静态字节板[67]
- 加载程序如何从动态模块分配/取消分配静态数据
- 使用单一实例分配静态成员
- 我如何分配静态RtMidi回调对象明智