Выдает alloca () память, если выброшено исключение?

Я поддерживаю устаревшее приложение C ++, которое, кажется, имеет медленную утечку памяти. Мне удалось «исправить» утечку памяти, убедившись, что текущая конфигурация больше не выдает никаких исключений, и я также могу вызвать утечку и масштабировать ее, настроив ее так, чтобы она приводила ко многим исключениям.

Вся выделенная память выполняется с помощью alloca (), а не malloc (). Я объяснил это тем, что alloca () работает как сборщик мусора java и автоматически освобождает память при выходе из контекста.

Из-за того, что утечка так явно связана с создаваемыми исключениями, у меня есть теория, что alloca () не освобождает память, когда генерируются исключения.

Это вообще правдоподобно? Мне кажется, что это серьезный недостаток в alloca (), если это правда, но когда я запускаю Google alloca (), это, как правило, проблема.

Я был бы признателен за понимание любых экспертов.

0

Решение

Вполне вероятно, что проблема связана с уровнем косвенности.

Буквальный вопрос «делает alloca вернуть память, если выброшено исключение? «. И ответ на этот вопрос; он возвращает только память, которая была непосредственно выделена. Деструкторы не запускаются, и любой указатель-владелец внутри allocaВыделенная память просочилась.

3

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

В C ++ вы не должны использовать процедуры управления памятью C. В современном C ++ интеллектуальные указатели предоставляют вам детализированную сборку мусора.

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

НО Это также означает, что любые подходящие деструкторы на объекте никогда не будут вызываться. Это означает, что если объект выполняет свое собственное управление памятью, он не будет очищен (потому что деструктор не запускается для его очистки).

Хоть alloca() вероятно очень быстро Я думаю, что дополнительная нагрузка на управление памятью (в общем случае) не стоит; хотя, если у вас есть особая потребность в дополнительной скорости, это может стоить того.

Код выглядит так:

void func()
{
MyType* x = (MyType*)alloca(sizeof(MyType));

passXtoCFunctionThatDoesNotTakeOwnership(x);
}

Должно быть написано так:

void func()
{
std::unique_ptr<MyType> x = std::make_unique<MyType>();

passXtoCFunctionThatDoesNotTakeOwnership(x.get());
}

Если вы используете его для хранения массива объектов.

void func()
{
MyType* x = (MyType*)alloca(sizeof(MyType) * arraySize);

// STUFF
x[0].stuff();
}

Тогда лучше использовать std :: vector

void func()
{
std::vector<MyType> x;
x.reserve(arraySize);   // or resize() if that is appropriate

// STUFF
x[0].stuff();
}

Если вы используете его для простых объектов. Тогда вам, вероятно, следует просто объявить автоматические переменные:

void func()
{
MyType* x = (MyType*)alloca(sizeof(MyType));

x->myData = 5;
}

Вы должны просто объявить переменную:

void func()
{
MyType x;

x.myData = 5;
}
2

Из Linux человек

….

Поскольку пространство, выделенное alloca (), выделено в стеке
кадр, это пространство автоматически освобождается если функция вернет является
перепрыгнул через вызов longjmp (3) или siglongjmp (3).

….

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

…..

ошибки Есть нет индикации ошибок если кадр стека не может быть
продлен. (Однако после неудачного размещения программа может
в получить SIGSEGV сигнал, если он пытается получить доступ к нераспределенному
во многих системах alloca () не может быть использована внутри списка
аргументы вызова функции, потому что пространство стека зарезервировано
alloca () появится в стеке в середине пространства для
аргументы функции.

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

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