Как заставить компилятор MSVC исключить размещение в стеке больших временных объектов?

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


Обновить

Прочитав первые несколько ваших комментариев, я хотел бы уточнить мой вопрос:

  • Как я могу заставить компилятор MSVC исключить выделение большого стека?

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


Я недавно начал компилировать свои проекты с /GS, /sdl а также /analyze параметры компилятора. (Microsoft Visual C ++ 2015) С этими параметрами компилятор правильно предупреждает о сомнительных конструкциях кода. Однако я столкнулся с некоторыми предупреждениями о том, что я всегда думал, что это хороший стиль C ++.

Пожалуйста, посмотрите на следующий пример кода:

struct my_struct {
char  large_member[64000];
};

void do_something_else(my_struct & ms)
{
// the intent of the next line is to "clear" the ms object
ms = {};  // <-- here the compiler claims the large stack allocation

// ... do some more work with ms
}

my_struct oh_my = {}; // construction, apparently no large stack allocation

int main()
{
// ...
// do something with the oh_my object
//

do_something_else(oh_my);
}

Мне сказали, что стандартный C ++ способ очистки структуры следующий:

ms = {};

С /analyze Опция компилятора предупреждает об этом следующим образом (пример):

C: \ Dev \ MDS \ Proj \ MDSCPV \ Vaps_Common_lib \ camber_radar.cpp: 162: предупреждение: C6262: функция использует «144400» байтов стека: превышает / анализирует: размер стека «16384». Это распределение было сгенерировано компилятором временно для ‘struct BitmapBuffer’ в строке 162. Рассмотрите возможность перемещения некоторых данных в кучу.

Я думаю, что происходит следующее:

  • временный объект создается в стеке
  • временный объект копируется в переменную объекта

Я хотел бы видеть что-то вроде инициализации по умолчанию происходит там. По моему мнению, компилятор должен уметь оптимизировать распределение стека. Но, видимо (согласно предупреждению) компилятор этого не делает.
У меня вопрос такой: Как я могу заставить компилятор исключить выделение стека?
Теперь я начал заменять эти места следующим кодом:

std::memset(&ms, 0, sizeof(ms));

4

Решение

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

Размещение нового выражения решит вашу проблему: он создает объект по заранее выделенному адресу, используя предоставленный конструктор. Например, new(&ms) my_struct{} дает ту же семантику, что и ms = {}, Должен my_struct иметь Нетривиальный деструктор, явный вызов ms.~my_struct() должен предшествовать размещению нового. Для справки: новое выражение

Я предлагаю не использовать эту технику обычным способом. Это своего рода «черная магия» низкого уровня C ++. Хорошие компиляторы должны оптимизировать использование memset,

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

1

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

Других решений пока нет …

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