@iemazurkevich

Почему происходит утечка памяти?

Известно, что утечка памяти происходит в случае, если seed() бросает исключение.
Вот только я не совсем понимаю, почему.
void foo( std::shared_ptr< int > p, int init ) {
    *p = init;
}
int seed() {
    //some actions
}
foo( std::shared_ptr< int >( new int( 42 ) ), seed() );

Предположительно, все дело в том, что выделяется память для int( 42 ), но из-за брошенного исключения она мало того, что не освобождается, так еще и остается ни с чем не связанной.

Но я не уверен, что это так.
  • Вопрос задан
  • 2718 просмотров
Решения вопроса 1
@encyclopedist
Согласно стандарту, порядок вычислений может быть разным, в том числе таким:
tmp1 = new int(42);
tmp2 = seed();
tmp3 = std::shared_ptr<int>(tmp1);
foo(tmp3, tmp2);

В таком случае, если seed бросает исключение, возникает утечка памяти.
Именно для избежания этой проблемы в стандарте предусмотрена вспомогательная функция make_shared. Исправленный вариант вашего кода будет выглядеть так:
foo(std::make_shared<int>(42), seed());
Помимо безопасности, также можно получить повышение производительности, поскольку make_shared может сделать одно выделение памяти вместо двух.
Доп ссылки:
herbsutter.com/2013/05/29/gotw-89-solution-smart-p...
stackoverflow.com/questions/20895648/difference-in...

Update
Насчёт порядка вычислений стандарт говорит следующее:
[intro.execution] Paragraph 15:
When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note ] Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

Таким образом, вычисление этих tmp1 и tmp2 в нашем случае является неупорядоченным (unsequenced).
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы