常量局部变量数组在内存中用于'C'程序
我正在使用GCC 4.8.1,它似乎没有将常量变量局部存储到数据段中的main。 下面是3个这样的程序的代码和内存映射:
代码1:
int main(void)
{ //char a[10]="HELLO"; //1 //const char a[10] = "HELLO"; //2
return 0;
}
MEMORY MAP FOR ABOVE:
text data bss dec hex filename
7264 1688 1040 9992 2708 a.exe
代码2:
int main(void)
{
char a[10]="HELLO";
//const char a[10] = "HELLO";
return 0;
}
MEMORY MAP FOR 2:
text data bss dec hex filename
7280 1688 1040 10008 2718 a.exe
代码3:
int main(void)
{
//char a[10]="HELLO";
const char a[10] = "HELLO";
return 0;
}
MEMORY MAP FOR 3 :
text data bss dec hex filename
7280 1688 1040 10008 2718 a.exe
我没有看到3个代码之间的数据段有任何不同。 有人可以向我解释这个结果吗?
感谢预期!
这是应该发生的事情:
代码1:任何地方都没有储存。
代码2: a
存储在堆栈中。 它不存储在.data
。
代码3 a
要么存储在栈或.rodata
,这取决于它是否以恒定表达或不初始化。 优化器也可能决定将其存储在.text
(与代码一起)。
我没有看到3个代码之间的数据段有任何不同。
那是因为应该没有区别。 .data
用于具有静态存储持续时间的非常量变量,它们被初始化为非零值。
如果你的程序没有使用你的数组,那么编译器可以简单地优化这个对象。
从C标准:
(C99,5.1.2.3p1)“本国际标准中的语义描述描述了优化问题无关的抽象机器的行为”
和
(C99,5.1.2.3p3)“在抽象机器中,所有表达式都按照语义的规定进行评估,实际实现中不需要评估表达式的一部分,只要它能够推断出它的值没有被使用,并且没有必要的副作用(包括由调用函数或访问易失性对象引起的任何错误)“。
如果您在优化禁用( -O0
)或取决于您的编译器编译程序#3时仍然可以分配对象。 在你的情况下,它不会出现在data
和rodata
部分,但在text
部分,因此text
部分增加。
例如,在你的第三个例子中,在我的编译器中,生成的-O0
代码是(使用objdump -d
转储的):
00000000004004d0 <main>:
4004d0: 55 push %rbp
4004d1: 48 89 e5 mov %rsp,%rbp
4004d4: 48 b8 48 45 4c 4c 4f mov $0x4f4c4c4548,%rax
4004db: 00 00 00
4004de: 48 89 45 f0 mov %rax,-0x10(%rbp)
4004e2: 66 c7 45 f8 00 00 movw $0x0,-0x8(%rbp)
4004e8: b8 00 00 00 00 mov $0x0,%eax
4004ed: 5d pop %rbp
4004ee: c3 retq
4004ef: 90 nop
0x4f4c4c4548
是你的字符串在一个寄存器中移动的ASCII字符,然后推入堆栈。
如果我使用-O3
编译相同的程序,输出结果很简单:
00000000004004d0 <main>:
4004d0: 31 c0 xor %eax,%eax
4004d2: c3 retq
4004d3: 90 nop
和字符串未出现在data
或rodata
,它被简单地优化了。
上一篇: Where does constant local variable array go in memory for a 'C' program