开发者

C++ macros to ensure used memory is freed?

开发者 https://www.devze.com 2023-03-04 10:28 出处:网络
So I am a bit of a n00b and was reading about new, delete, and pointers, and I am certain that I will forget too many deletes over the course of my life.So I was wondering if a macro like the followin

So I am a bit of a n00b and was reading about new, delete, and pointers, and I am certain that I will forget too many deletes over the course of my life. So I was wondering if a macro like the following would be more trouble than it's worth.

#define withObject(ptr, value, BODY)                       \
{                                                           \
     ptr = value;                                           \
     BODY                                                   \
     delete ptr;                                            \ 
     ptr=NULL                                               \
}

Would this macro cause some prob开发者_运维技巧lems or behave in an unexpected way?

Edit: oops I left off the d on freed. Well thanks everyone for the answers.


No, do not do this. It won't prevent either memory leaks or stray pointers. Instead, read up on smart pointers. The current standard provides one in the shape of auto_ptr, but many more (and better ones) are available, depending on your C++ platform.

Also, I suspect you may be over-using new and delete - they should be used very rarely in your code. You should prefer to use values. So instead of something like this:

string * s = new string ( "foobar" );
....
delete s;

you should simply write:

string s( "foobar" );

and have the compiler manage the lifetime of the string for you.


No need to reinvent the wheel here, you are looking for smart pointers.

The very useful Boost library has smart pointer functionality.


google RAII idiom; it is the same but not so hacky; you can then apply this on your dynamic allocations using the ubiquitous smartpointers (which automatically free memory when they go out of use/scope).

Boost contains the most famous/widespread version of a smart pointers (seveal flavours).

The C++ standard has always had a kind of crippled smart pointer, named auto_ptr. This is one with caveats but useful in it's own right (RTFM!).

C++0x adopts several of the Boost TR1 classes, including the most popular smart pointer (I hope I'm wording this right because the standardese is usually quite specific on details)

HTH


You're looking for the smart pointer pattern. It's standard C++ and explained in detail at this site.


Aside from the fact that you really should use smart pointers (even the lowly auto_ptr will serve for your purpose), there's possible problems with BODY. Using a potentially large section of code as an argument for a function-like macro has its own traps. For example, if there's an unparenthesized comma in BODY, then BODY turns to two arguments. I'm not sure of further issues, because I've never seen anybody try it.

Don't use function-like macros in C++. It's rarely worth it.


It looks like you wish to allocate an object, do a short piece of work on it, then delete it. For this purpose I would suggest std::auto_ptr.


The idiomatic C++ way to do this sort of thing is not with macros, but with "smart pointer" classes that use Resource Acquisition is Initialization. For instance, Boost's scoped_ptr would work nicely in the contexts where your macro would make sense.

I'll put a sketch of a smart pointer class here - but I'm leaving out a lot of details. This is just to give you an idea of how they work. Use scoped_ptr instead, they didn't leave anything out.

template <typename T>
class smartptr<T> {
public:
    smartptr() : ptr(new T) {}
    smartptr(T* p) : ptr(p) {}
    ~smartptr() { delete ptr }
    T& operator*() { return *ptr; }
    T* operator->() { return ptr; }
private:
    T* ptr;
}


Would this macro cause some problems or behave in an unexpected way?

If BODY throws an exception then the delete will be skipped.

The solution is to make use of the "RAII" idiom. It's one of the most important concepts in modern C++ programming.


I think a better solution would make an allocate and delete macro instead of an all-inclusive. Thats a really messy, not very helpful thing to do

When I program in C I commonly do something like the following:

#define ALLOC_ARY(type, sz) (type*)calloc(sz, sizeof(type))
#define ALLOC_STR(sz) ALLOC_ARY(char, sz)

char *string = ALLOC_STR(128);
int *array = ALLOC_ARY(int, 20);

But remembering to free in vanilla C is just part of it:

free(string); string = NULL;
free(array); array = NULL;

Edit: For C++, smart pointers as others have suggested are a good way to go.

0

精彩评论

暂无评论...
验证码 换一张
取 消