C: память стека, goto и "переход в область идентификатора с измененным типом",
Я обнаружил, что это отказывается компилировать:
int test_alloc_stack(int size){
if(0) goto error; // same issue whatever conditional is used
int apply[size];
give_values(apply,size);
return 1;
error:
return 0;
}
Ошибка, которую я получаю, это: "перейти в область идентификатора с измененным типом".
Ликвидация линии с помощью "goto" и переход к ошибке решают проблемы.
Если я использую динамическое распределение для применения, проблема также исчезнет. Это прекрасно компилируется:
int test_alloc_heap(int size){
if(0) goto error;
int * apply = calloc(sizeof(int),size);
give_values(apply,size);
free(apply);
return 1;
error : return 0;
}
Что происходит?
Ответы
Ответ 1
Объявление:
int apply[size];
создает массив переменной длины. Когда он выходит из сферы действия, компилятор должен создать код, который очищает выделение для этого массива. Мне кажется, что входить в сферу действия такого объекта запрещено, потому что некоторым реализациям может потребоваться некоторая инициализация, требуемая для кода очистки, и если вы перейдете в область действия, инициализация будет обойдена.
Если вы переходите к динамическому распределению, инициализация и очистка становятся вашей ответственностью, а не компилятором.
Ответ 2
Это запрещено стандартом:
Стандарт C99, пункт 6.8.6.1
Ограничения
[...] Утверждение goto должно не перепрыгивать извне пределы идентификатора, имеющего переменный модифицированный тип внутри области этого идентификатора.
Это именно то, что делает ваш goto
, а именно: прыгать извне рамки apply
внутрь.
Вы можете использовать следующее обходное решение для ограничения области apply
:
if(0) goto error;
{
int apply[size];
give_values(apply,size);
return 1;
}
error:
return 0;
Ответ 3
Ваш goto
позволяет пропустить строку, которая выделяет apply
(во время выполнения).
Вы можете решить проблему одним из четырех способов:
1: перепишите свой код, чтобы вы не использовали goto.
2: Переместите объявление apply
до goto
.
3: измените область действия, чтобы error:
вышла за пределы области apply
:
int test_alloc_stack(int size){
if(0) goto error; // same issue whatever conditional is used
{
int apply[size];
give_values(apply,size);
return 1;
}
error:
return 0;
}
4: измените объявление переменной, чтобы его размер можно было определить во время компиляции.