функция удаления размещения никогда не вызывается при исключении - PullRequest
0 голосов
/ 30 ноября 2018

Удаление размещения используется для освобождения памяти, когда возникает исключение в новом месте размещения.Итак, я запустил тест:

#include <iostream>
#include <new>
using namespace std;
class A {
public:
    A(){
        cout << "constructor" << endl;
        throw 1;
    }
};

void* operator new(size_t size, int i){
    cout << "in placement new" << endl;
    return ::operator new(size);
}

void operator delete(void *ptr, int i){
    cout << "in placement delete" << endl;
    ::operator delete(ptr);
}

int main(){
    int o = 9;
    A* a = new(o) A;
}

И функция удаления размещения никогда не вызывалась, она просто выходила.Почему?

Ответы [ 4 ]

0 голосов
/ 30 ноября 2018
class A {
public:
    A(){
        cout << "constructor" << endl;
        throw 1;
    }

    void* operator new(size_t size, int i){
        cout << "in placement new" << endl;
        return ::new A();
    }

    void operator delete(void *ptr){
        cout << "in placement delete" << endl;
        ::operator delete(ptr);
    }
};

int main(){
    int o = 9;
    try
    {
        A* a = new(o) A;
    }
    catch(...)
    {
        cout << "Exception"<< endl;
    }
}

Лучше использовать оператор перегрузки на уровне класса.Также вы должны использовать блок try / catch.

0 голосов
/ 30 ноября 2018

Это потому, что вы не перехватываете исключение, поэтому не вызывается соответствующий код для вашего удаления.Просто оберните его в блок try / catch:

try 
{
    int o = 9;
    A* a = new(o) A;
} 
catch (int i) { }

Помните, что вы должны эффективно перехватить исключение, созданное вашим конструктором, а не просто исключение.

0 голосов
/ 30 ноября 2018

Размещение operator delete finction вызывается , если вы правильно обрабатываете исключение.

Если вы не обрабатываете исключение, реализация может завершить вашу программу сразу послеthrow без раскручивания стека, поэтому, например, никакие деструкторы не называются .

0 голосов
/ 30 ноября 2018

Ваша программа генерирует необработанное исключение.Это означает, что std::terminate вызывается.

В этой ситуации может быть или не быть разматывание стека (это определяется реализацией независимо от того, происходит ли это).Ваша реализация явно решает вызвать std::terminate без выполнения разматывания стека.

Вызов operator delete на самом деле является частью разматывания стека , даже если здесь не используется стек, этобит неправильного числа.

Чтобы увидеть, как вызывается ваша функция, измените код на:

try
{
    A* a = new(o) A;
}
catch(...) {}

.

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