Утечка памяти при обработке исключений - PullRequest
4 голосов
/ 27 апреля 2020

Я просто перехожу на C ++ из C, и в настоящее время пробиваю путь через исключения.

Мне трудно понять, почему у меня возникает утечка памяти в этой простой программе:

#include <iostream>  /* I/O */
#include <exception> /* exception */
#include <cstdlib>   /* stdlib */

using namespace std;

void Bar()
{
    throw exception();
}

void Foo()
{
    int *ip = new int;

    try
    {
        Bar();    
    }
    catch(exception &e)
    {
        cerr << "Foo: Exception caught: " << e.what() << endl;
        delete ip;
        exit(1);
    }

    delete ip;
}

int main()
{
    Foo();
    return 0;
}

Я чувствую, что упускаю что-то важное здесь, но не могу указать на это. Есть идеи?

Вывод Valgrind:

==21857== Memcheck, a memory error detector
==21857== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==21857== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==21857== Command: ./a.out
==21857== 
Foo: Exception caught: std::exception
==21857== 
==21857== HEAP SUMMARY:
==21857==     in use at exit: 136 bytes in 1 blocks
==21857==   total heap usage: 3 allocs, 2 frees, 72,844 bytes allocated
==21857== 
==21857== 136 bytes in 1 blocks are possibly lost in loss record 1 of 1
==21857==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21857==    by 0x4ECD8FF: __cxa_allocate_exception (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==21857==    by 0x108CCC: Bar() (ex33.cpp:9)
==21857==    by 0x108D0C: Foo() (ex33.cpp:18)
==21857==    by 0x108DBD: main (ex33.cpp:31)
==21857== 
==21857== LEAK SUMMARY:
==21857==    definitely lost: 0 bytes in 0 blocks
==21857==    indirectly lost: 0 bytes in 0 blocks
==21857==      possibly lost: 136 bytes in 1 blocks
==21857==    still reachable: 0 bytes in 0 blocks
==21857==         suppressed: 0 bytes in 0 blocks
==21857== 
==21857== For counts of detected and suppressed errors, rerun with: -v
==21857== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Ответы [ 2 ]

7 голосов
/ 27 апреля 2020

Вы не должны вызывать exit в C ++. Деструкторы локальных объектов называться не будут. И причина стека не будет разобрана, похоже, что деструктор исключения также не будет вызван.

Из стандарта:

18.1.2 Когда выбрасывается исключение, управление передается ближайший обработчик с подходящим типом (18.3); «Ближайший» означает обработчик, для которого составной оператор или инициализатор ctor после ключевого слова try последний раз был введен потоком управления и еще не завершен.

18.1.3 Вызов исключения копирует-инициализирует (11.6 , 15.8) временный объект, называемый объектом исключения. Значение l, обозначающее временную, используется для инициализации переменной, объявленной в соответствующем обработчике (18.3). Если тип объекта исключения будет неполным типом или указателем на неполный тип, отличный от cv void, программа некорректна.

Стек не разматывается: деструкторы переменных с automati c срок хранения не называется. Цитата здесь

0 голосов
/ 27 апреля 2020

Как оказалось, замена exit(1) из Foo() на return; устранила утечку памяти.

Итак, мой дополнительный вопрос, почему я не могу позвонить exit() из Foo()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...