07 Jun, 2006, kiasyn wrote in the 1st comment:
Votes: 0
While reading Darien's STRALLOC/STRFREE fix i discovered an
easy way to find DISPOSE and CREATE calls that haven't been changed when they should be. (For constructors and destructors)

Say you recently changed.. EXTRA_DESCR_DATA to a class..
In your DISPOSE macro you would change:

#define DISPOSE(point)  \
do \
{ \
if (point)) \
{ \
free((point)); \
(point) = NULL; \
} \
} while(0)

To:
#define DISPOSE(point)  \
do \
{ \
if ( (typeid(point)) == typeid(EXTRA_DESCR_DATA *) ) \
{ \
bug( "DISPOSING EXTRA_DESCR_DATA %s:%d", __FILE__, __LINE__ ); \
delete (point); \
(point) = NULL; \
break; \
} \
if (point)) \
{ \
free((point)); \
(point) = NULL; \
} \
} while(0)


This would print a bug message when DISPOSE was used on an EXTRA_DESCR_DATA pointer, delete it properly and exit the macro. (You also need to #include <typeinfo> at the top of mud.h)
07 Jun, 2006, Omega wrote in the 2nd comment:
Votes: 0
nice usage, same basic setup for my strfree/stralloc update release, where it checks to see if the 'disposed' type is a char* or const char *, if so, it checks it in the hash_table, and if it is, it strfree's it :)
07 Jun, 2006, Guest wrote in the 3rd comment:
Votes: 0
Don't forget that after doing delete(point) you should also do point = NULL.

The delete function doesn't null the pointer and you can get some strange results back from that later down the line. I've run into this more than once already.
07 Jun, 2006, Omega wrote in the 4th comment:
Votes: 0
I completely agree with samson..

If you fail to null the pointer, it will bust hardcore later on while doing debugging, and give false problems.

(grumbles)

Best recommendation is to go through with the nullification of
the data after disposal/deletion
08 Apr, 2007, Dorian wrote in the 5th comment:
Votes: 0
I know this thread is old, but I thought I could help.

No offense, but this is a really poor way to do it. There is no need to perform a run-time check when this can be handled at compile time:

template<typename T> void safe_dispose(T* &ptr); //Intentionally left w/o a body

#define DIPOSEABLE(type) \
template<> void safe_dispose<type>(type* &ptr) \
{ \
std::free(ptr); \
ptr = 0; \
}

#define DISPOSE(ptr) safe_dispose(ptr)

DISPOSEABLE(const char)


Or similar. This is an opt-in strategy, but an opt-out strategy could work as well. I just think this would catch more errors although the initial implementation time might be high for needing to put in all the types that could be used in the DISPOSE marco.
10 Apr, 2007, Guest wrote in the 6th comment:
Votes: 0
#define DISPOSE(point)                         \
do \
{ \
if( (point) ) \
{ \
if( typeid((point)) == typeid(char*) || typeid((point)) == typeid(const char*) ) \
{ \
if( in_hash_table( (char*)(point) ) ) \
{ \
log_printf( "&RDISPOSE called on STRALLOC pointer: %s, line %d\n", __FILE__, __LINE__ ); \
log_string( "Attempting to correct." ); \
if( str_free( (char*)(point) ) == -1 ) \
log_printf( "&RSTRFREEing bad pointer: %s, line %d\n", __FILE__, __LINE__ ); \
} \
else \
delete[] (point); \
} \
else \
free( (point) ); \
(point) = NULL; \
} \
else \
(point) = NULL; \
} while(0)


So something like this wouldn't be a good thing? Considering the DISPOSE and STRFREE macros are common causes of problems in Smaug muds this C++ macro seems to do the job well enough. Unless I've missed the whole point of your macro and template.
10 Apr, 2007, Dorian wrote in the 7th comment:
Votes: 0
Quote
So something like this wouldn't be a good thing? Considering the DISPOSE and STRFREE macros are common causes of problems in Smaug muds this C++ macro seems to do the job well enough. Unless I've missed the whole point of your macro and template.


I think I was a little unclear. When I said "bad", I didn't mean that it was a worthless macro. I just meant that you could handle the situation better. The DISPOSE and STRFREE macros both do a run-time check of the type. The template I suggested does a compile-time check. Both methods accomplish the same goal: correctly disposing the the allocated memory. The benefit of my method is that when the wrong type is passed to safe_dispose, a compilation error is risen. This way the mistke of passing the incorrect pointer is caught at compile-time rather than at run-time allowing for it to be corrected before the MUD is even run.
Does that make sense? Hopefully I have been clear.
10 Apr, 2007, kiasyn wrote in the 8th comment:
Votes: 0
^__^ very nice.
11 Apr, 2007, Guest wrote in the 9th comment:
Votes: 0
Alright, tried to give this a go. Doing the following:
template<typename T> void safe_dispose(T* &ptr); // Intentionally left w/o a body

#define DISPOSEABLE(type) \
template<> void safe_dispose<type>(type* &ptr) \
{ \
free(ptr); \
ptr = NULL; \
}

#define DISPOSE(ptr) safe_dispose((ptr))
DISPOSEABLE(const char*)


Yielded several of these:
Quote
o/shell.o: In function `void safe_dispose<char const*>(char const**&)':
/home/samson/Alsherok/src/mud.h:739: multiple definition of `void safe_dispose<char const*>(char const**&)'
o/mudmsg.o:/home/samson/Alsherok/src/mud.h:739: first defined here


So I commented out the DISPOSEABLE statement, and just ended up with half a screen full of
Quote
/home/samson/Alsherok/src/shell.cpp:885: undefined reference to `void safe_dispose<char>(char*&)'
/home/samson/Alsherok/src/shell.cpp:886: undefined reference to `void safe_dispose<char>(char*&)'
/home/samson/Alsherok/src/shell.cpp:885: undefined reference to `void safe_dispose<char>(char*&)'
/home/samson/Alsherok/src/shell.cpp:886: undefined reference to `void safe_dispose<char>(char*&)'

scattered about over a bunch of files.

I'm not sure if I've done something wrong or if gcc 4.1 just doesn't like this. I'm also wondering exactly how this will protect using STRFREE on something that should get DISPOSEd since str_alloc and str_dup both accept a const char* as an argument, but the results are handled quite differently.
11 Apr, 2007, Davion wrote in the 10th comment:
Votes: 0
If you have
DISPOSEABLE(const char*)

in a .h file, then that's probably where you're getting your multiple definition error. It is the code for the function.

For
DISPOSEABLE(const char*)

You probably want
DISPOSEABLE(const char)
11 Apr, 2007, Tyche wrote in the 11th comment:
Votes: 0
Why would one dynamically allocate and deallocate a const pointer? :devil:
11 Apr, 2007, Guest wrote in the 12th comment:
Votes: 0
Davion said:
For
DISPOSEABLE(const char*)

You probably want
DISPOSEABLE(const char)


Doing that leads to an invalid conversion error. I figured out the part about multiple definition. Commented out the DISPOSABLE call but it still complained about the other undefined references.

The question becomes then, am I even doing this right? Should a disposal be done by calling DISPOSEABLE( ch->name ) or in some other manner?
11 Apr, 2007, Davion wrote in the 13th comment:
Votes: 0
Tyche said:
Why would one dynamically allocate and deallocate a const pointer? :devil:

Good point. Ignore me.
12 Apr, 2007, Guest wrote in the 14th comment:
Votes: 0
So nobody has anything to offer on what I might be doing wrong?
12 Apr, 2007, Dorian wrote in the 15th comment:
Votes: 0
Samson said:
Alright, tried to give this a go. Doing the following:
template<typename T> void safe_dispose(T* &ptr); // Intentionally left w/o a body

#define DISPOSEABLE(type) \
template<> void safe_dispose<type>(type* &ptr) \
{ \
free(ptr); \
ptr = NULL; \
}

#define DISPOSE(ptr) safe_dispose((ptr))
DISPOSEABLE(const char*)


Yielded several of these:
Quote
o/shell.o: In function `void safe_dispose<char const*>(char const**&)':
/home/samson/Alsherok/src/mud.h:739: multiple definition of `void safe_dispose<char const*>(char const**&)'
o/mudmsg.o:/home/samson/Alsherok/src/mud.h:739: first defined here


Okey dokey. Let's make a few changes to my implementation to correct some shortcomings:

template<typename T> void safe_dispose(T *&ptr); //Intentionally left undefined

//Yes, BOTH functions are needed
#define DISPOSABLE(type) \
template<> inline void safe_dispose<type>(type *& ptr) \
{ \
std::free(ptr); \
ptr = 0; \
}\
template<> inline void safe_dispose<type>(const type*& ptr)\
{\
std::free(ptr);\
ptr = 0;\
}


Good? Yes.

Quote
So I commented out the DISPOSEABLE statement, and just ended up with half a screen full of
Quote
/home/samson/Alsherok/src/shell.cpp:885: undefined reference to `void safe_dispose<char>(char*&)'
/home/samson/Alsherok/src/shell.cpp:886: undefined reference to `void safe_dispose<char>(char*&)'
/home/samson/Alsherok/src/shell.cpp:885: undefined reference to `void safe_dispose<char>(char*&)'
/home/samson/Alsherok/src/shell.cpp:886: undefined reference to `void safe_dispose<char>(char*&)'

scattered about over a bunch of files.


This is intentional by design. You want the compiler to give you an error when you pass a variable of some type that hasn't been declared DISPOSABLE. This is the benefit of a compile-time check over a run-time check.

Quote
I'm also wondering exactly how this will protect using STRFREE on something that should get DISPOSEd since str_alloc and str_dup both accept a const char* as an argument, but the results are handled quite differently.


As such:

DISPOSABLE(CHAR_DATA)
DISPOSABLE(some_other_diku_type)
//THERE IS NO DISPOSABLE(char)!

//Yes, the two functions are BOTH needed
inline void str_free(char *&ptr )
{
//string freeing code
ptr = 0;
}

inline void str_free(const char *&ptr )
{
//string freeing code
ptr = 0;
}


Assuming str_free takes the place of STRFREE, you have now set up a basic system where only DISPOSABLE types will be able to be used in safe_dispose and only char * types can be used in str_free. Anytime these are mixed up, the compiler will generate an error telling you the types are incompatible.

I hope this makes sense. This is also not to say the system isn't perfect. A lot could be done to improve it, but this is just a rudimentary sample on how templates can catch a lot of your errors if you utilize the type system.
12 Apr, 2007, Conner wrote in the 16th comment:
Votes: 0
Samson said:
So nobody has anything to offer on what I might be doing wrong?


I'd offer, but honestly I don't think I could begin to offer anything productive. Memory management in code is one of my weakest areas. The whole STRFREE/DISPOSE thing confuses me badly, and you're using C++ which I have not learned at all yet. :sad:
0.0/16