2013-09-12 5 views
2

Следующий код использует кучу:Можно ли вернуть VLA?

char* getResult(int length) { 
    char* result = new char[length]; 
    // Fill result... 
    return result; 
} 

int main(void) { 
    char* result = getResult(100); 
    // Do something... 
    delete result; 
} 

Так result должен быть удален где-то, предпочтительно владельцем.

ниже код, от того, что я понимаю, использовать расширение под названием VLA, который является частью C99, а не часть стандарта C++ (но поддерживаются GCC и другие компиляторы):

char* getResult(int length) { 
    char result[length]; 
    // Fill result... 
    return result; 
} 

int main(void) { 
    char* result = getResult(100); 
    // Do something... 
} 

Правильно ли я полагаю, что result по-прежнему выделяется в стеке в этом случае?

Является ли result копией, или это ссылка на память для мусора? Является ли вышеуказанный код безопасным?

+3

VLA - это красная сельдь. Вы возвращаете адрес переменной, выходящей из области действия, периода. –

+0

@KerrekSB Я не хочу быть придирчивым, но масштабы и продолжительность жизни - это разные понятия. Когда вы вызываете функцию, переменная, объявленная в области блока, также выходит за пределы области видимости, но ее время жизни не заканчивается. – ouah

+0

@ouah: Да, true: «Переменная, чья жизнь заканчивается, поскольку она выходит из сферы действия», я должен был сказать. –

ответ

5

Правильно ли я полагаю, что в этом случае результат по-прежнему распределяется по стеклу?

Исправить. VLA имеют автоматическую продолжительность хранения.

В результате получается копия, или это ссылка на память для мусора? Является ли вышеуказанный код безопасным?

Код не является надежным. Адрес, возвращенный getResult, является недопустимым адресом. Разделение указателя вызывает неопределенное поведение.

+0

@ShafikYaghmour VLA в GNU C и в GNU C++ имеют такое же поведение, как и в C99. – ouah

4

Вы не можете вернуть его в C будет иметь автоматическую продолжительность хранения (объект не будет действовать, как только вы выходите из сферы) и возвращение будет вызывать undefined behavior из раздела C99 draft standard6.2.4длительности хранения объектов пункт :

Для такого объекта, который действительно имеет тип переменной длины массива, его срок службы не распространяется от декларации объекта до выполнения O f программа оставляет область декларации .27) Если область вводится рекурсивно, каждый экземпляр объекта создается каждый раз. Начальное значение объекта является неопределенным.

В C++ мы должны полагаться на документы, так как это расширение в этом случае и gcc docs on VLA говорит, что он удаляется, когда область заканчивается:

Эти массивы объявлены как и любой другой автоматические массивы, но с длиной, которая не является постоянным выражением. Хранилище выделяется в точке объявления и освобождается, когда область блока, содержащая объявление, завершается.

0

Когда вы вернетесь с getResult(), массив символов result выйдет за пределы области действия и будет освобожден вместе с фреймом стека для вызова функции. Если вы хотите сохранить структуру функций, вам нужно позвонить malloc, а затем освободить память.

+0

«Сфера применения» - неправильный термин; «время жизни» массива «результат» заканчивается, когда функция возвращается. Идентификаторы имеют область действия. У объектов есть время жизни. Объекты могут быть доступны даже тогда, когда их идентификаторы находятся вне области видимости, например, когда указатель на объект правильно передается подпрограмме, которая не может видеть ее объявление. –

Смежные вопросы