Thread: Need Help for New Operator Behaviour

  1. #1
    Registered User
    Join Date
    Jun 2010
    Posts
    103

    Need Help for New Operator Behaviour

    Hi All

    I created a program for allocating array of objects dynamically using operator overloading of new Operator. Below is the code. I have not implemented the code for deletion of array of objects as I want to understand the behavior of construction first.

    Code:
    //OverNew.h
    
    class OverNew
    {
      int age;
      std::string name;
    
    public:
    	void* operator new(size_t) throw(bad_alloc);
    	void* operator new[](size_t) throw(bad_alloc);
    	void operator delete(void*);
    
            OverNew(int,std::string); 
    	 void getData();
    	 OverNew(int);
    	 OverNew();
           ~OverNew();
    };
    Code:
    //OverNew.cpp
    #include<iostream>
    #include<string>
    
    using namespace std;
    
    #include "OverNew.h"
    
    OverNew::OverNew(int a,string str)
    {
    	cout <<" \n Inside 2 Parameter Ctr";
        age = a;
    	name = str;
    }
    OverNew::OverNew(int a)
    {
       age = a;
       cout << "\n Inside Ctr:"<<age;
    }
    
    OverNew::OverNew()
    {
       cout << "\n Inside Empty Ctr";
    }
    
    void* OverNew::operator new( size_t size) throw(bad_alloc)
    {
      
    	
    	cout << "\n Inside Operator New :"<<size; 
    	void *ptr;
    	try
    	{
    	   ptr = malloc(size);
        }
    	catch (bad_alloc)
    	{
    		cout<<"Memory Exception";
    	}
    	
    	return ptr;
    }
    
    
    void* OverNew::operator new[] (size_t size) throw(bad_alloc)
    {
      
    	
    	cout<<"\n Inside Array of New Operator:"<<size;
    	return new OverNew(size);
    }
    
    void OverNew::operator delete( void *m)
    {
    	cout<<"\n Inside Overload operator Delete";
    	if (!m ) 
    		return ;
    
    	free(m);
      
    }
    
    
    OverNew::~OverNew()
    {
       cout <<"\n Inside Destructor";
       
    }
    
    void OverNew::getData()
    {
      cout<<age <<"\t" <<name;
    
    }
    
    int main()
    {
     
    
    	OverNew *N = new OverNew[10];
    
    //	 delete N;
    	 getchar();
         return 0;
    }
    When I execute this program: Below is the output:

    Inside Array of New Operator:168
    Inside Operator New :16
    Inside Ctr:168
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    Inside Empty Ctr
    I want to understand that what is this output means:
    Inside Array of New Operator:168
    So since my class has one integer and one string variable so total sum is 12. Since we are creating array of objects , I am assuming 4 bytes to this pointer which result in total 16 bytes.
    So I am creating 10 objects so : 10 * 16 = 160
    but it is coming as 168 size. why?

    Since I am not passing any parameter, I expect that one parameter constructor should not called. But it is called and also 10 empty constructor too. I want to know for which object, this parameter constructor was called?

    Can Any body help me understanding this?

    Thanks
    Nickman

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I don't know about new[], but there are a few things I'd like to point out.

    malloc does not throw. Ever. C functions do not throw. Ever. Therefore, your try/catch is superfluous. If malloc fails, it returns nullptr.

    As for your signatures, e.g.: void* operator new(size_t) throw(bad_alloc);
    I'd like to point out a few things. First, do not remove the parameter name, so it really should be:
    void* operator new(size_t size) throw(bad_alloc);
    The compiler may not require it, but it hurts readability. So don't do that.
    Secondly, throw specifiers are deprecated. If your functions throws an exception, you shouldn't put anything in there. If it does not throw an exception (e.g. like your function currently does), then you should add noexcept:

    void* operator new(size_t size); // This function may throw
    void* operator new(size_t size) noexcept; // This function never throws (if it DOES throw and you throw something, you will a runtime error)

    Inside your operator new, IF malloc would throw an exception (which it doesn't), it would mean you your ptr would be uninitialized and you would be returning that, resulting in undefined behavior. Always initialize your variables and listen to compiler warnings. Some compilers warn about returning or using uninitialized variables.

    Oh, and regarding the "this" pointer:
    A class does not store any "this" pointer, so the extra 4 bytes does not come from there. The "this" pointer is a "hidden" argument to each member function so they can identify where in memory that instance lies. No, the extra bytes probably comes from padding.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Jun 2010
    Posts
    103
    Thanks Elisa for pointing of those points. I have to put try catch in main from where I am creating objects and bad_alloc will be thrown by operator new.
    I have changed that.

    Ok I got you point too of cell padding. I forgot to consider that point.

    But one question is still want to know. The call for one parameter constructor. Why that constructor called when I am creating zero arguments object.

    Thanks
    Nickman

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    but it is coming as 168 size. why?
    O_o

    When you use `delete[]' are you telling the compiler how many elements to destroy?

    Nope. You use `delete[]' and the environment determines the number of elements to destroy.

    The compiler then needs some place to store information about how many elements are allocated so that the correct number of elements can be destroyed.

    *shrug*

    Your compiler, it seems, stores that information in part of the allocated storage.

    delete N;
    WRONG!

    If you use `new[?]', you must use `delete[]' or face undefined behavior.

    You are also missing the related implementation for the `operator delete[]' function which means, depending on the compiler, that all the allocated objects may not be destroyed properly if an exception is raised during construction of an element of the array.

    I want to know for which object, this parameter constructor was called?
    Your implementation for the `operator new[]' function is fatally flawed.

    The line `return new OverNew(size);' is allocating memory for one--"Inside Operator New :16 "--object and passing the value `size' to the constructor for that allocated objected.

    If you want to use a shared implementation for both the `operator new' and `operator new[]' functions, you should move the shared mechanism into a separate function to be called by both interfaces.

    The errors related to the buggy implementation means that you are trampling memory you do not own.

    Your code, basically, contains a well hidden overflow bug.

    [Edit]
    C functions do not throw. Ever.
    The C language has no native exception mechanism, but the lack of a native exception mechanism does not prevent code from using other means which would raise an exception. Using C code doesn't give a pass on considering the possibility of an exception.
    [/Edit]

    Soma
    Last edited by phantomotap; 02-01-2015 at 06:57 AM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by nickman View Post
    But one question is still want to know. The call for one parameter constructor. Why that constructor called when I am creating zero arguments object.
    I do not see this. In your output, it clearly calls the default constructor (as expected).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Jun 2010
    Posts
    103
    Yes. I agree that operator delete[] shoulb be implemented and I mention in post too that I have not implemented that I want to understand the behavior of construction first.

    I have changed the implementation and rather that calling:
    Code:
    void* OverNew::operator new[] (size_t size) throw(bad_alloc)
    {
      
    	
    	cout<<"\n Inside Array of New Operator:"<<size;
    	return new OverNew(size);
    I am using this:

    Code:
    void* OverNew::operator new[] (size_t size) throw(bad_alloc)
    {
      
    	
    	cout<<"\n Inside Array of New Operator:"<<size;
    
    
        void *ptr;
        ptr = malloc(size);
     	
    	return ptr;
    }
    It's now printing as what I was expecting. Below is whole code.

    Code:
    #include<iostream>
    #include<string>
    
    using namespace std;
    
    #include "OverNew.h"
    
    OverNew::OverNew(int a,string str)
    {
    	cout <<" \n Inside 2 Parameter Ctr";
        age = a;
    	name = str;
    }
    
    OverNew::OverNew(int a)
    {
       age = a;
       cout << "\n Inside Ctr:"<<age;
    }
    
    
    OverNew::OverNew()
    {
       cout << "\n Inside Empty Ctr ";
    }
    
    
    
    void* OverNew::operator new( size_t size) throw(bad_alloc)
    {
      
    	
    	cout << "\n Inside Operator New :"<<size; 
    	void *ptr;
        ptr = malloc(size);
     	
    	return ptr;
    }
    
    
    void* OverNew::operator new[] (size_t size) throw(bad_alloc)
    {
      
    	
    	cout<<"\n Inside Array of New Operator:"<<size;
       //	return new OverNew(size);
    
    	void *ptr;
        ptr = malloc(size);
     	
    	return ptr;
    }
    
    void OverNew::operator delete( void *m)
    {
    	cout<<"\n Inside Overload operator Delete";
    	if (!m ) 
    		return ;
    
    	free(m);
      
    }
    
    
    void OverNew::operator delete[]( void *m)
    {
       cout<<"\n Inside Overload Array operator Delete";
    	
      //  delete(m);
    
    
    	if (!m ) 
    		return ;
    
    	free(m);
    
    }
    
    OverNew::~OverNew()
    {
       cout <<"\n Inside Destructor";
       
    }
    
    void OverNew::getData()
    {
      cout<<age <<"\t" <<name;
    
    }
    
    int main()
    {
     
    	OverNew *N;
    	try
    	{
    	      N = new OverNew[10]();
    	}
    	catch (bad_alloc)
    	{
    		cout<<"Memory Exception";
    	}
    	
    	 delete []N;
    	 getchar();
         return 0;
    }
    Thanks
    Nickman

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Oh yes, this line:
    return new OverNew(size);
    creates a new OverNew object on the heap and initializes it by calling the constructor OverNew(int), which is probably not what you wanted.
    You probably meant
    return new OverNew[size];
    (Note the brackets.)
    Which tells the compiler that you want 10 objects, all default initialized.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    You probably meant
    return new OverNew[size];
    o_O

    Did you even look at the context of the error?

    The line `return new OverNew[size];' is also certainly not wanted.

    1): The `size' parameter of the `operator new' functions isn't representative of the number of elements.
    2): The call would invoke infinite recursion.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    1) Slipped my mind.
    2) I didn't consider that.
    I was only commenting along the lines about it calling the int constructor and not actually doing a sized allocation.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. strange behaviour
    By cfanatic in forum C Programming
    Replies: 9
    Last Post: 07-13-2012, 10:41 PM
  2. coma operator behaviour
    By nkrao123@gmail. in forum C Programming
    Replies: 2
    Last Post: 09-07-2011, 07:08 AM
  3. unkown behaviour
    By krishna in forum C Programming
    Replies: 2
    Last Post: 04-06-2009, 09:11 AM
  4. Replies: 3
    Last Post: 12-09-2008, 11:19 AM
  5. Replies: 16
    Last Post: 04-20-2008, 01:15 PM