我有以下代码:
void function(char *str)
{
int i;
char buffer[strlen(str) + 1];
strcpy(buffer, str);
buffer[strlen(str)] = '\0';
printf("Buffer: %s\n", buffer);
}
我希望这段代码会抛出编译时错误,因为'缓冲区'在堆栈上分配具有运行时相关长度(基于strlen())。但是在GCC中,编译通过了。这是如何运作的?缓冲区是动态分配的,还是仍然是堆栈本地的,分配的大小是多少?
答案 0 :(得分:2)
C99允许可变长度数组。不在C99中编译代码不会给出任何错误,因为GCC还允许可变长度数组作为扩展。
<强> 6.19 Arrays of Variable Length 强>
ISO C99允许使用可变长度自动数组,作为扩展GCC在C90模式和C ++ 中接受它们。
答案 1 :(得分:1)
通过反汇编您的功能,您可以轻松验证:
$ objdump -S <yourprogram>
...
void function(char *str)
{
4011a0: 55 push %ebp
4011a1: 89 e5 mov %esp,%ebp
4011a3: 53 push %ebx
4011a4: 83 ec 24 sub $0x24,%esp
4011a7: 89 e0 mov %esp,%eax
4011a9: 89 c3 mov %eax,%ebx
int i;
char buffer[strlen(str) + 1];
4011ab: 8b 45 08 mov 0x8(%ebp),%eax
4011ae: 89 04 24 mov %eax,(%esp)
4011b1: e8 42 01 00 00 call 4012f8 <_strlen>
4011b6: 83 c0 01 add $0x1,%eax
4011b9: 89 c2 mov %eax,%edx
4011bb: 83 ea 01 sub $0x1,%edx
4011be: 89 55 f4 mov %edx,-0xc(%ebp)
4011c1: ba 10 00 00 00 mov $0x10,%edx
4011c6: 83 ea 01 sub $0x1,%edx
4011c9: 01 d0 add %edx,%eax
4011cb: b9 10 00 00 00 mov $0x10,%ecx
4011d0: ba 00 00 00 00 mov $0x0,%edx
4011d5: f7 f1 div %ecx
4011d7: 6b c0 10 imul $0x10,%eax,%eax
4011da: e8 6d 00 00 00 call 40124c <___chkstk_ms>
4011df: 29 c4 sub %eax,%esp
4011e1: 8d 44 24 08 lea 0x8(%esp),%eax
4011e5: 83 c0 00 add $0x0,%eax
4011e8: 89 45 f0 mov %eax,-0x10(%ebp)
....
无论如何,这里的相关部分是sub %eax,%esp
。这表明堆栈是根据之前返回的strlen
扩展的,以便为缓冲区腾出空间。