取消全局替换操作符new返回的指针的未分配行为,而不调用替换操作符delete吗? (C ++ 17)

问题描述 投票:1回答:2

[SL operator delete未返回的非空指针上调用SL operator new被认为是未定义的行为,如此处针对(1)和(2)所述:https://en.cppreference.com/w/cpp/memory/new/operator_delete

除非ptr是空指针或是以前从operator new(size_t)operator new(size_t, std::nothrow_t)的标准库实现中获得的指针,否则此函数的标准库实现的行为是不确定的。

因此,混合使用operator newoperator deleteoperator new[]operator delete[]的行为也是不确定的行为。我在标准说明中找不到任何内容,说明这是否也适用于调用用户分配方法的替换operator newoperator delete。例如:

void* operator new(std::size_t p_size)
{
    void *ptr = UserImplementedAlloc(p_size);
    return ptr;
}

void* operator new[](std::size_t p_size)
{
    void *ptr = UserImplementedAlloc(p_size);
    return ptr;
}

void operator delete(void* p_ptr)
{
    UserImplementedFree(p_ptr);
}

void operator delete[](void* p_ptr)
{
    UserImplementedFree(p_ptr);
}

以下内容是否不确定?假设UserImplementedAlloc总是返回正确的地址,而不是nullptr

struct Simple
{
    explicit Simple(); //Allocates m_bytes
    ~Simple(); //Frees m_bytes
    char * m_bytes;    
};

/*Placement new is not replaced or overridden for these examples.*/

//Example A
{
    //Allocates and invokes constructor
    Simple* a = new Simple();
    //Invokes destructor
    a->~Simple();
    //Deallocates
    UserImplementedFree(static_cast<void*>(a));
}

//Example B
{
    //Allocates
    void* addr = UserImplementedAlloc(sizeof(Simple));
    //Invokes constructor
    Simple* b = new (addr) Simple();
    //Invokes destructor and deallocates
    delete b;
}

我不是在寻找关于这是否不好的方法的演讲,我只是在试图确定这是否是定义的行为。

c++ memory-management new-operator undefined-behavior delete-operator
2个回答
1
投票

即使分配和释放功能是用户定义的,使用deletenew[]delete[]new的确是UB。这样做的原因是,在分配数组时,编译器有时需要能够编写一个计数器,该计数器告诉它在看到delete[]调用时要调用多少个析构函数。如果将newdelete[]配对,则后者可能会读取一些希望找到计数器的内存,并进行一些无意义的操作。如果将new[]delete配对,则后者只能调用一个析构函数。

在C ++ 17中,引用为[expr.delete] / 2:

...在第一种选择(删除对象)中,delete的操作数的值可以是空指针值,即指向由先前的[[new-表达式,或指向表示该对象基类的子对象(4.5)的指针(第13条)。如果不是,则行为是不确定的。在第二种选择(删除数组)中,delete的操作数的值可以是空指针值,也可以是由先前数组new-expression产生的指针值。如果不是,则行为是不确定的。 ...


0
投票
您的编译器的delete版本可能知道一些隐藏在实现中的,依赖于该类型的已删除指针。

首先手动调用析构函数,然后删除void *是不安全的。您不会在C ++语义中删除相同的指针。

© www.soinside.com 2019 - 2024. All rights reserved.