2014-07-16 128 views
1

我有以下代碼:緩衝區分配使用的strlen()

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中編譯通過。這個怎麼用?動態分配緩衝區,還是仍然是堆棧本地,分配的大小是多少?

+4

這是有效的C99,是的,它根據它計算的大小在堆棧上分配。 –

+0

@mafso你爲什麼說這會導致未定義的行爲? – dragosht

+2

你已經標記了兩種不同的語言。這在(現代)C中是有效的,但不是(標準)C++。你在用哪個? –

回答

2

C99允許可變長度陣列。在C99中編譯你的代碼不會給出任何錯誤,因爲GCC也允許可變長度數組作爲擴展。

6.19 Arrays of Variable Length

可變長度自動數組被允許在ISO C99,和作爲擴展GCC接受他們在C90模式和C++

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進行了擴展以獲得緩衝區的空間。