Почему профиль памяти объекта должен быть известен во время компиляции для размещения в стеке?

Кажется, это общепризнанный факт, что если вы создаете экземпляр объекта на языке, подобном C ++, он имеет право на размещение в стеке (а не на выделение кучи), если размер объекта известен во время компиляции. Например, массив фиксированного размера может помещаться в стек, но элементы вектора будут помещаться в кучу, поскольку окончательный размер неизвестен во время компиляции.

Почему это так? Почему пространство стека не может быть динамически выделено во время выполнения путем перемещения указателя стека?

РЕДАКТИРОВАТЬ: Для пояснения, вот пример: в середине функции вы вычисляете неконстантное целое число. Если вы хотите создать массив этого размера, выделение должно выполняться в куче, потому что размер массива неизвестен во время компиляции. Но почему вы не можете просто поместить массив на вершину стека при его создании?

2

Решение

Рассмотрим этот код:

void extend(std::vector<int>& v, int val) {
int w = abs(val);
v.push(w)
}

std::vector<int> v(10);
extend(v, 3);

Если содержание v находится в стеке, оно не будет непрерывным, так как между v [9] и вновь выдвинутым v [10] есть другие вещи. Хуже того, если операция принудительная, то v [10] почти наверняка что-то перезапишет.

2

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

Вы можете сделать это с помощью функции alloca() для GCC, и функции _alloca() а также _malloca() для компиляторов Microsoft.

Это выглядит следующим образом:

void allocatesArray(int i)
{
char *ray = reinterpret_cast<char*>(alloca(i));
// 'i' bytes of memory allocated, returns void *

ray[0] = 'a';
// space freed, pointer invalidated
}

Имейте в виду, что это не считается очень хорошей практикой из-за неопределенного поведения в случае переполнения стека.

1

То, что вы не можете сделать, если вы не находитесь на самой вершине стека, это изменение размера, так как вы не можете перемещать весь стек вокруг. Если у вас есть какая-то структура данных, которая может каким-либо образом изменить размер, вы не можете использовать ее при любом вызове функции из вашей текущей области с неконстантным контекстом.

Если вы просто думаете об этом как о возможном способе оптимизации вещей, clang уже делает так называемое «решение для кучи», чтобы выполнить такие виды оптимизации, когда это применимо.

0
По вопросам рекламы [email protected]