Распределение буфера в стеке с помощью 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 компиляция проходит. Как это работает? Распределяется ли буфер динамически, или, если он все еще является локальным стеком, каков его размер?

1

Решение

С99 позволяет массивы переменной длины. Некомпилирование вашего кода в C99 не даст никакой ошибки, потому что GCC также допускает массив переменной длины в качестве расширения.

6.19 Массивы переменной длины:

Автоматические массивы переменной длины разрешены в ISO C99, и в качестве расширения GCC принимает их в режиме C90 и в C ++.

2

Другие решения

Разобрав вашу функцию, вы можете легко проверить это:

$ 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 вернулся раньше, чтобы получить место для вашего буфера.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector