CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5

Hybrid View

  1. #1
    Join Date
    Sep 2009
    Posts
    28

    operator new with protected destructor

    I came across a very odd problem in VC++.

    I defined a class in upnumber.h

    Code:
    #ifndef UPNUMBER_H
    #define UPNUMBER_H
    
    #include <string>
    
    class UPNumber{
    	std::string name;
    	static bool onTheHeap;
    	void _init(const std::string& s);
    protected:
    	~UPNumber();
    public:
    	//UPNumber(){}
    	UPNumber(int initValue);
    	UPNumber(const UPNumber& rhs);
    	UPNumber(const std::string& s = "UPNumber");
    	static void* operator new(size_t size);
    	static void* operator new[](size_t size);
    	static void operator delete(void* p){::delete p;};
    	static void operator delete[](void* p){::delete[] p;};
    	class HeapConstraintViolation{};
    
    	void destroy() const{delete this; }
    };
    
    #endif UPNUMBER_H
    //-------------------------------------------------------------------------






    The implementation file is upnumber.cpp
    Code:
    #include "upnumber.h"
    #include <iostream>
    #include <string>
    #include <exception>
    #include <new>
    
    using namespace std;
    
    bool UPNumber :: onTheHeap = false;
    
    UPNumber::~UPNumber(){cout << "delete " << name << endl;}
    UPNumber::UPNumber(int initValue) : name("UPNumber"){_init(name);}
    UPNumber::UPNumber(const UPNumber& rhs): name(rhs.name){_init(name);}
    UPNumber::UPNumber(const string& s) : name(s) {_init(name);}
    
    void UPNumber::_init(const string& s){
    	if(!onTheHeap){
    		throw HeapConstraintViolation();
    	}
    	cout << "create " << name << endl;
    	onTheHeap = false;
    }
    
    void* UPNumber :: operator new(size_t size){
    	onTheHeap = true;
    	return :: operator new(size);
    }
    
    void* UPNumber :: operator new[](size_t size){
    	onTheHeap = true;
    	return :: operator new[](size);
    }
    //-------------------------------------------------------------------------




    Finally the test file: test.cpp
    Code:
    #include "upnumber.h"
    #include <string>
    #include <iostream>
    using namespace std;
    
    
    int main(){
    	UPNumber* p = new UPNumber("UPNumber");
    	p->destroy();
    	UPNumber* parray = new UPNumber[1]; ///???????????
    	//parray->destroy(100);
    	return 0;
    }
    For statement: UPNumber* parray = new UPNumber[1]; I got compilation error: error C2248: 'UPNumber::~UPNumber' : cannot access protected member declared in class 'UPNumber'

    But I even did not call delete function here. If just using UPNumber* parray = new UPNumber, the code can be complied without any problem. What is hidden behavior for compiler on the array new operation? Why the new operation will be related to the destructor?
    Last edited by CJIAJIA; September 13th, 2009 at 11:44 PM.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: operator new with protected destructor

    First, use code tags when posting code.

    Second, you don't need all of that code to reproduce the problem:
    Code:
    class UPNumber
    {
      protected:
          ~UPNumber();
       public:
           UPNumber();
    };
    
    int main()
    {
        UPNumber* parray = new UPNumber[1]; 
    }
    The Comeau compiler gives the following error:
    Code:
    Thank you for testing your code with Comeau C/C++!
    Tell others about http://www.comeaucomputing.com/tryitout !
    
    Your Comeau C/C++ test results are as follows:
    
    Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
    Copyright 1988-2008 Comeau Computing.  All rights reserved.
    MODE:strict errors C++ C++0x_extensions
    
    "ComeauTest.c", line 11: error: "UPNumber::~UPNumber()" (declared at line 4) is
              inaccessible
          UPNumber* parray = new UPNumber[1]; 
                                 ^
    
    1 error detected in the compilation of "ComeauTest.c".
    
    In strict mode, with -tused, Compile failed
    Now that it is simplified to this small example, others can comment on the issue. The problem has something to do with the way C++ handles array new, user-defined constructors, and lookup of the corresponsing delete for the array new.

    If you take away the user defined constructor, the code compiles. I'm not sure exactly what the ANSI spec says, since I don't have the ANSI spec handy right now.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    May 2009
    Posts
    2,413

    Re: operator new with protected destructor

    Quote Originally Posted by Paul McKenzie View Post
    Now that it is simplified to this small example, others can comment on the issue. The problem has something to do with the way C++ handles array new, user-defined constructors, and lookup of the corresponsing delete for the array new.

    If you take away the user defined constructor, the code compiles. I'm not sure exactly what the ANSI spec says, since I don't have the ANSI spec handy right now.
    In section 5.3.4 New, the C++ standard has this paragraph,

    ---

    16. If the new-expression creates an object or an array of objects of class type, access and ambiguity control are done for the allocation function, the deallocation function (12.5), and the constructor (12.1). If the new expression creates an array of objects of class type, access and ambiguity control are done for the destructor
    (12.4).

    ---

    Note that in the second sentence it states that when an array of objects is created, it's checked whether the object destructor can be accessed. This is not done when just an object is created.

    I don't know the reason for this difference but my guess is that if the creation fails in the array case there may be an attempt do destruct already created objects in the array, and that of course would require the object destructor to be accessible.

  4. #4
    Join Date
    Aug 2007
    Posts
    858

    Re: operator new with protected destructor

    It makes sense if you think about it a bit. When you create a single object on the heap, the dtor isn't needed until delete is used (which will then fail to compile).

    When you create an array of objects on the heap, if the objects in question contain only POD types and has a compiler implemented ctor, the only way the creation of the array should fail is if operator new[] fails to allocate memory - before any of the objects are actually constructed. The user defined dtor should not be needed.

    However, if the class has a user defined ctor, then that ctor may potentially throw during the creation of the array objects, meaning that the dtor needs to be accessible for any objects in the array which were constructed before the throw.

  5. #5
    Join Date
    Sep 2009
    Posts
    28

    Thumbs up Re: operator new with protected destructor

    thanks all! And for Paul McKenzie, thanks for your reminder. Since I am new here, I don't know code tag yet when I post this topic. But I will add it in my forthcoming post.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured