James
James

Reputation: 1589

Checking to see if a pointer can be freed

I've looked all over for an answer to this but can't seem to find one. (I have fairly limited experience with C++)

In my library, I free a string. (Amazing, huh?)

This is where the problem arises. I have a struct which contains a char* that may be allocated on the heap or may not be. While it is a valid pointer it cannot be freed.

IE

char* s1 = "A String";
char* s2 = (char*)memcpy(malloc(9), s1, 9);

free(s2);
free(s1);

Will cause an error on "free(s1);" (As it should) Because s1 does not actually need to be freed, (It isn't on the heap) how can I handle this in an "acceptable" way? (On similar topics the answer of "let it crash" didn't seem reasonable IMO)

Because the struct is not solely created by the library, it is not possible to guarantee that a string will be properly copied over using something like memcpy.

Seeing as this is a windows library, I don't need to worry about using ISO C stuff or standard C functions.

Upvotes: 5

Views: 1490

Answers (7)

Hank
Hank

Reputation: 547

For things involving memory allocation in C++, smart pointers are awesome. Just sayin'.

http://www.cplusplus.com/reference/std/memory/auto_ptr/

http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/smart_ptr.htm

Upvotes: 0

Ben Voigt
Ben Voigt

Reputation: 283684

Seeing as this is a Windows library, make the argument a BSTR. Then you require the user to allocate it properly (with SysAllocString) and you're guaranteed to use a matching deallocator.

Other methods are just... bad. If your user has a different compiler, then you can't free() the string even if they did use malloc.

[Note: Converted from a comment at James's request, this really is just a Windows-specific case of the last of his suggestions]

Further note: BSTR is Unicode. I kinda sorta remember seeing a way to use the BSTR allocator to store ANSI strings, seems that SysAllocStringByteLen does that, but be warned that putting ANSI data in a BSTR will be highly counterintuitive to anyone familiar with BSTR.

Upvotes: 2

axw
axw

Reputation: 7083

I have done something similar in the past, where I would use a stack-allocated string in some cases, and a heap-allocated string in others, but they ultimately get passed off to some other common code.

What I have done in that case, is to have two pointers. One is either NULL, or a heap-allocated string. The other pointer points to either the stack-allocated or the same heap-allocated memory as the former. When you go to do your free(), you check the former pointer only.

Of course, that's going to look nasty in an exposed API. In my case it was internal code only.

Upvotes: 0

Jonathan Wood
Jonathan Wood

Reputation: 67223

Store all strings in the heap, then you'll know they all need to be freed. If the string exists as in global memory, copy it to a heap buffer.

Upvotes: 0

wilhelmtell
wilhelmtell

Reputation: 58677

This is the sort of thing that's known at compile time. You look at the code and know what to free and what not to. So don't think of a way to defer it to runtime, because apart from the fact you won't find a way in this case, it's the wrong way of doing things in C++. When you can do it statically, do it statically.

Use the type system. Use RAII.

Upvotes: 0

Neilvert Noval
Neilvert Noval

Reputation: 1695

You can malloc char *s1 and place "A String" as value. After that, you can free s1.

Upvotes: 0

James McNellis
James McNellis

Reputation: 355079

In C++, you shouldn't be worrying about this at all. Use std::string and have it manage memory for you, automatically. Don't manage memory manually.

If you were to do this manually, you would need to manage the resource yourself, by

  • making the user of the library manage the memory himself, or
  • requiring the user to tell you how to manage the memory, or
  • telling the user how you are going to manage the memory and then expecting the user to comply.

Upvotes: 6

Related Questions