Почему мои деструкторы не вызываются при вызове из таймера обратного вызова win32? - PullRequest
1 голос
/ 18 января 2012

Я только что задал этот вопрос .Короче говоря, при вызове обратного вызова таймера win32 исключение, похоже, никуда не денется.Кажется, что-то там тайно обрабатывается Windows.

Хорошо, это проблема.Другая сторона проблемы заключается в том, что деструкторы, кажется, не вызываются, когда выдается это исключение.В следующем коде для std::vector для CFoo выводится «~ CFoo» только тогда, когда временные файлы в GetFooVect разрушаются и когда rValue копируется в fooVect.Содержимое fooVect НЕ уничтожено.

Это мой худший кошмар.Я использую RAII довольно сильно.Я довольно сильно опираюсь на свои деструкторы для надлежащей очистки.

class CFoo
{
public:
    ~CFoo() {printf(__FUNCTION__ "\n");}
};

std::vector< CFoo > GetFooVect()
{
    std::vector< CFoo > rValue;
    rValue.push_back(CFoo());
    rValue.push_back(CFoo());
    rValue.push_back(CFoo());
    return rValue;
}

VOID CALLBACK Timer(HWND hwnd,
    UINT uMsg,
    UINT_PTR idEvent,
    DWORD dwTime)
{
    // My destructors aren't called?
    std::vector< CFoo> fooVect = GetFooVect();

    // I'm destroyed
    CFoo aFoo;

    throw FooExcept();
    printf("Also Here\n");
}

Я пытался воссоздать это, просто выбрасывая / перехватывая исключения C ++ (т.е. удаляя переменную обратного вызова таймера win32), и вектор CFoo просто отлично разрушает,По какой-то причине деструкторы НЕ вызываются здесь для вещей в векторах.Что дает?Есть ли логическое объяснение этому, или это просто странно, или оба?

1 Ответ

6 голосов
/ 18 января 2012

Вы никогда не должны позволять исключению распространяться через границу C API (как обратный вызов SetTimer).Код C (и функции Windows API) ничего не знают об исключениях языка C ++.Вы не можете полагаться на такой код для распространения ваших исключений.

Ваш обратный вызов должен перехватывать все исключения языка C ++ перед возвратом и обрабатывать исключения соответствующим образом.Если вам нужно как-то сообщить об исключениях для остальной части вашего приложения, вы должны сделать это самостоятельно.

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

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