Как заставить компилятор 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));
1 ответ
Поскольку my_struct
легко копируется, компиляторы должны иметь возможность разместить memset
позвоните вместо создания временного и затем назначьте его, но это не обязательно.
Новое выражение Placement решит вашу проблему: оно создает объект по заранее выделенному адресу, используя предоставленный конструктор. Например, new(&ms) my_struct{}
дает ту же семантику, что и ms = {}
, Должен my_struct
есть нетривиальный деструктор, явный вызов ms.~my_struct()
должен предшествовать размещению нового. Для справки: новое выражение
Я предлагаю не использовать эту технику обычным способом. Это своего рода "черная магия" низкого уровня C++. Хорошие компиляторы должны оптимизировать использование memset
,
Кстати, oh_my
Глобальная переменная не выделяет временную переменную в стеке, потому что она инициализируется константой во время компиляции.