【问题标题】:Deleting an aliased pointer删除别名指针
【发布时间】:2011-09-23 14:20:47
【问题描述】:

这样做:

 union{
     int * integer;
     char * character;
 } u;
 u.integer = new int;
 delete u.character;

 u.integer = new int[5];
 delete [] u.character;

我认为如果这些类型中的任何一个具有非平凡的析构函数,这将不起作用,但这可以吗?

【问题讨论】:

标签: c++ pointers unions delete-operator


【解决方案1】:

这在任何情况下都工作,如果我们假设工作意味着具有明确定义的行为而不是看起来工作(即没有崩溃)

【讨论】:

  • 确实应该不够好;我可以回答说“它总是有效并且定义完美”,而你将无法选择哪个是正确的。
【解决方案2】:

不,这是未定义的行为,无论该项目是否具有微不足道的析构函数。如果析构函数是微不足道的,它可能看起来“工作”,而实际上它正在泄漏内存等。

【讨论】:

  • 它甚至可能不会泄漏内存......它只是未定义:)
【解决方案3】:

我要说这介于实现定义和未定义之间。

5.3.5/2:“在第一个选择(删除对象)中, delete 的操作数可能是...指向 a 的指针 由先前的新表达式创建的非数组对象...。

按照您的方式使用时,指针的值不会改变,所以这应该可以按预期工作,前提是sizeof(char*) == sizeof(int*)。该特定比较的结果是实现定义的,如果假设为假,则行为未定义。

所以真的不是特别安全。

【讨论】:

    【解决方案4】:

    很容易看出这是一个危险的错误。这两种类型可能具有完全不同且不兼容的内存分配和释放方式。这包括填充、垃圾收集、簿记、特定于类的内存操作等。不要这样做。

    #include <cstddef>
    #include <cstdlib>
    #include <iostream>
    
    using namespace std;
    
    class A
    {
    
        public:
    
            void* operator new (size_t size)
            {
                cout << "A::operator new (size_t)" << endl;
                return malloc(size);
            }
    
            void* operator new [] (size_t size)
            {
                cout << "A::operator new [] (size_t)" << endl;
                return malloc(size);
            }
    
            void operator delete (void* ptr)
            {
                cout << "A::operator delete (void*)" << endl;
                free(ptr);
            }
    
            void operator delete [] (void* ptr)
            {
                cout << "A::operator delete [] (void*)" << endl;
                free(ptr);
            }
    
    };
    
    class B
    {
    
        public:
    
            void* operator new (size_t size)
            {
                cout << "B::operator new (size_t) with some B-specific stuff" << endl;
                return malloc(size);
            }
    
            void* operator new [] (size_t size)
            {
                cout << "B::operator new [] (size_t) with some B-specific stuff" << endl;
                return malloc(size);
            }
    
            void operator delete (void* ptr)
            {
                cout << "B::operator delete (void*) with some B-specific stuff" << endl;
                free(ptr);
            }
    
            void operator delete [] (void* ptr)
            {
                cout << "B::operator delete [] (void*) with some B-specific stuff" << endl;
                free(ptr);
            }
    
    };
    
    
    int main (int, char**)
    {
    
        union{
            A* a;
            B* b;
        } u;
    
        u.a = new A();
        delete u.b;
    
        u.a = new A[5];
        delete [] u.b;
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-09
      • 2010-09-08
      • 2021-12-29
      • 2018-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多