Click here to Skip to main content
15,884,007 members
Articles / Programming Languages / C

new(local) for safer and simpler code with no need for smart-pointer template wrappers

Rate me:
Please Sign up or sign in to vote.
4.65/5 (20 votes)
25 Oct 2012CPOL8 min read 92.6K   387   26  
reduce bugs and memory leaks by using new(local)
// Simple scope object to keep  track and deallocate dynamic objects when leaving scope
// Article url: http://www.codeproject.com/Articles/468126/Local-NEW-or-Automatic-heap-cleanup-when-leaving-s
//
// Example: { Scope local; A* a=new(local) A(); } 
// We left scope. Object "a" will be destroyed along with associated "local"scope object
// 
// Author : Ladislav Nevery

#ifndef SCOPE_H
#define SCOPE_H

#ifdef __cplusplus

#ifdef WIN32

struct  Lock : CRITICAL_SECTION { // we separated critical section to keep code portable
	    Lock() { InitializeCriticalSection(this); }
	   ~Lock() { DeleteCriticalSection(this);     }
   void lock() { EnterCriticalSection(this);      }
 void unlock() { LeaveCriticalSection(this);      }
};

#endif//WIN32

struct Scope { // This is non thread safe version for speed in local scope. From threads use thread safe TScope variant defined below
       struct Obj { virtual ~Obj() {} };
              Obj**               pointer; int pointers; int capacity;     char* is_obj; Lock* lock;
	   Scope(int Capacity=10)  :  pointer(0) , pointers(0),  capacity(Capacity), is_obj(0) ,   lock(0){}
      ~Scope() 
	   { 
		   for(int i=pointers-1;i>=0;i--) {
			  if(pointer[i]) {
				  if(is_obj[i]) pointer[i]->~Obj(); // if what we stored is pointer to object call it's destructor first
				  free(pointer[i]);
			  }
		   }
		  free(pointer);
		  free(is_obj);
		  if(lock) delete lock;
	   }

	   void add(void* Pointer, int Is_obj) 
	   { 
		    if(lock) lock->lock();

			if( capacity  < pointers+1 || !pointer ) {
				capacity  = capacity+capacity>>1;
				pointer   = (Obj**)realloc(pointer, capacity * sizeof(Obj*) );
				is_obj    = (char*)realloc(is_obj,  capacity * sizeof(char) );
			}

			pointer[pointers] = (Scope::Obj*)Pointer; 
			 is_obj[pointers] = Is_obj;

			pointers++;
			if(lock) lock->unlock();
	   }

	   void del(void* Pointer) 
	   {
		    if(lock) lock->lock();
			for(int i=0;i<pointers;i++) {
				if( pointer[i]==Pointer) {
					pointer[i]=0; 
					break;
				}
			}
			if(lock) lock->unlock();
	   }
};

// TScope is hread safe version of scope it is defined as separate type since it's slower
struct TScope : public Scope { 
	TScope(int Capacity=1000) : Scope(Capacity) {
		lock=new Lock();  
	}
};

// scoped versions of object oriented memory functions memory of whose we release by calling delete 
// which in turn calls their virtual destructors followed by internal call of standard free() when leaving scope

inline void * __cdecl operator new(unsigned int size,Scope& scope) 
{
    void *pointer = malloc(size); 
	scope.add(pointer,true);  
	return(pointer);
};

inline void   __cdecl operator delete(void* pointer,Scope& scope) 
{
	scope.del(pointer); 
	((Scope::Obj*)pointer)->~Obj();
	free(pointer);
}

// scoped versions of old C malloc based memory functions memory of whose we release by calling free() when leaving scope

inline char* strdup(Scope& scope, const char* text) 
{
	char* pointer = strdup(text); 
	scope.add(pointer,false); 
	return(pointer);
}

inline void* malloc(Scope& scope, size_t size) 
{
	void* pointer = malloc(size); 
	scope.add(pointer,false); 
	return(pointer);
}

inline void* calloc(Scope& scope, size_t size, size_t cnt) 
{
	void* pointer = calloc(size,cnt); 
	scope.add(pointer,false); 
	return(pointer);
}

inline void free(Scope& scope, void* pointer) 
{
	scope.del(pointer); 
	free(pointer);
}

#else  // pure C language version of Scope 

#ifdef WIN32

   void* lock_create()  { 
	   void* lock=calloc(sizeof(CRITICAL_SECTION),1);
	   InitializeCriticalSection((CRITICAL_SECTION*)lock); 
	   return lock;
   }
   void lock_destroy(void* lock) { 
	   DeleteCriticalSection((CRITICAL_SECTION*)lock);     
	   free(lock);
   }
   void  Lock  (void* lock) { EnterCriticalSection((CRITICAL_SECTION*)lock);      }
   void  Unlock(void* lock) { LeaveCriticalSection((CRITICAL_SECTION*)lock);      }

#endif//WIN32

typedef struct Scope_ { // This is non thread safe version for speed in local scope. From threads use thread safe TScope variant defined below
        struct Scope*    prev;  void* pointer;  void* lock;
} Scope;

Scope* create_scope(int thread_safe) {
	Scope* scope=(Scope*)calloc(sizeof(Scope),1);
	if(thread_safe) scope->lock=lock_create();
	return scope;
}

void destroy_scope(Scope* scope) { 
	if(scope->pointer) free(scope->pointer);
	destroy_scope(scope->prev); 
	if(scope->lock) { lock_destroy(scope->lock);  }
}

void scope_add(Scope* scope,void* pointer) 
{ 
	if(scope->lock) Lock(scope->lock);
	if(scope->pointer) { // make copy of current pointer and his type as a child
		Scope* Prev=(Scope*)calloc(sizeof(Scope),1); 
		Prev->prev=scope->prev; 
		Prev->pointer=scope->pointer; 
		Prev->lock=scope->lock;
		scope->prev=Prev; 
	}
	scope->pointer=pointer; 
	if(scope->lock) Unlock(scope->lock);
}

void scope_del(Scope* scope,void* pointer) 
{
	Scope* s;
	if(scope->lock) Lock(scope->lock);
	for(s=scope;  s; s=s->prev) {
		if(s->pointer==pointer) s->pointer=0;
	}
	if(scope->lock) Unlock(scope->lock);
}


char* strdup_(Scope* scope, const char* text) 
{
	char* pointer = strdup(text); 
	scope_add(scope,pointer); 
	return(pointer);
}

void* malloc_(Scope* scope, size_t size) 
{
	void* pointer = malloc(size); 
	scope_add(scope,pointer); 
	return(pointer);
}

void* calloc_(Scope* scope, size_t size, size_t cnt) 
{
	void* pointer = calloc(size,cnt); 
	scope_add(scope,pointer); 
	return(pointer);
}

void free_(Scope* scope, void* pointer) 
{
	scope_del(scope,pointer); 
	free(pointer);
}

#endif // ! __cplusplus = end of C version

#endif //SCOPE_H

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Slovakia Slovakia
Past Projects:
[Siemens.sk]Mobile network software: HLR-Inovation for telering.at (Corba)
Medical software: CorRea module for CT scanner
[cauldron.sk]Computer Games:XboxLive/net code for Conan, Knights of the temple II, GeneTroopers, CivilWar, Soldier of fortune II
[www.elveon.com]Computer Games:XboxLive/net code for Elveon game based on Unreal Engine 3
ESET Reasearch.
Looking for job

Comments and Discussions