2017-01-18 1 views
3

Как я понял, следующий код генерирует массивы переменной длины (через нестандартное расширение C++).Есть ли способ проверить, созданы ли массивы переменной длины в стеке/куче?

int main() 
{ 
    int valone = rand(); 
    int valtwo = rand(); 
    int array[valone][valtwo]; 
    // Printing size 
    cout << sizeof(array) << endl; 
} 

Есть ли способ проверить, сгенерирован ли его на стек или кучу? Описание wikipedia here говорит, что gcc генерирует то же самое в стеке, но когда я пытался использовать код выше, размер массива кажется слишком большим, чтобы вписаться в стек, но он никогда не жалуется.

Примечание: Этот код работает только с GCC & звоном, а не с визуальной студией

+0

Ссылка на Википедию вы указываете на C99, а не на C++. 'gcc' может или не может обрабатывать код C99 и код C++. –

+3

Не уверен насчет стандартного способа (так же как и «стандарт» применим для «нестандартного расширения»), но для быстрого тестирования вы можете сравнивать адреса 'valtwo' и' array [0] '. Если массив находится в стеке, они должны быть смежными. Если бы на куче, они были бы совсем другими. Это не на 100% надежнее, но будет работать большую часть времени. – Mikhail

+0

Вероятно, он не будет жаловаться, пока вы не получите доступ к внешнему временному хранилищу, но кто знает наверняка? – user4581301

ответ

1

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

«Никогда не жалуется», я полагаю, вы имеете в виду, что программа не сбой.

Вы никогда не прикасаетесь к памяти, которую вы выделяете, и компилятор был достаточно умен, чтобы доказать это, и ничего не выделял.

Возьмём адрес переменной, и отправить его в функцию, которая определена в другом месте:

int array[valone][valtwo] = {}; 
cout << &array << endl; 

Теперь компилятор был не совсем уверен, что массив никогда не обращались. Это связано с тем, что он не может войти в оператор потоковой передачи, который реализован в другой единицы перевода. Возможно, оператор будет разыменовывать указатель; мы должны убедиться, что массив существует.

Segfault разбил эту программу с моей первой попытки. Стек была переполнена.

Я предполагаю, что такой тест на краш-тест - это способ проверить, находится ли VLA в стеке.

Предложение Михаила в комментариях сравнить смежность автоматических переменных с VLA является достойной платформозависимой идеей, но она может работать только в том случае, если вы выделяете достаточно небольшое количество VLA, чтобы она не разбивала программу.

0

Сначала я полагаю, вы знаете, что любой кусок памяти, выделенный в куче, используя либо таНос нового или продолжает срок службы всей программы, если явно не высвобождены , Таким образом, мы можем заключить, что если массив переменной длины существует только в пределах его области действия, но не в течение срока действия программы, он скорее всего будет выделен в стеке.

Я не знаю, имеются ли случаи, когда в куче выделяется патрон памяти, но ведет себя так, как если бы он был членом стека. Лучше всего увидеть код сборки для этого. Такая реализация, вероятно, будет использовать функции динамического распределения/syscalls под капотом.

Если это похоже на утку, она ходит как утка и говорит как утка, тогда должно быть безопасно предположить, что это утка (большую часть времени).

+1

Я думаю, что ваши рассуждения в первом абзаце ошибочны. Если фрагмент памяти может быть выделен неявно, то неявно выделенный фрагмент также может быть освобожден неявно. Вполне возможно, что VLA будет реализован с помощью malloc. – user2079303

+0

Это может быть, и именно по этой причине во втором абзаце я утверждаю, что не знаю, есть ли случай, когда распределение происходит в куче, но ведет себя так, как оно является членом стека. Другой способ рассуждения - это то, что выделяется в стеке, определяется во время компиляции. Это не относится к VLA в целом. Насколько я знаю, все, что выделяется во время выполнения, должно быть выделено в кучу. Таким образом, у нас есть дилемма, в которой требования к распределению требуют, чтобы пространство было распределено в куче, поскольку оно разрешено во время выполнения, но ведет себя так, как если бы оно являлось членом стека по правилам области. – ugar

+0

Истинное обследование, я думаю, потребует знать адресное пространство кучи в виртуальном адресном пространстве. – ugar

1

Это может быть сложным вопросом, и я попробовал некоторые вещи, как

#include "iostream" 

int Stack_or_heap(void* ptr) 
{ 
int dummy; 
return ptr > &dummy; 
} 

int main(int argc, char** argv) 
{ 
    int* i = new int(); 
    int x, y, z; 
    std::cout << Stack_or_heap(&x) << Stack_or_heap(&y) << Stack_or_heap(&z) << Stack_or_heap(i); 
} 
+0

Это не совсем надежный, но и умный, и этой идеи может быть достаточно для op. В случае op вы можете работать с int непосредственно рядом с массивом и проверять, находятся ли адреса массива и int рядом друг с другом – WorldSEnder

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