使用strlen()在堆栈中进行缓冲区分配

时间:2014-07-16 14:01:24

标签: c++ c stack c99

我有以下代码:

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中,编译通过了。这是如何运作的?缓冲区是动态分配的,还是仍然是堆栈本地的,分配的大小是多少?

2 个答案:

答案 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扩展的,以便为缓冲区腾出空间。