Skip to main content
GameDev.net gamedev.net
🔒 Locked

C Question

Started by cold_storm Aug 28, 2006 at 6:09 PM 7 replies 1.1k views
Original Post
cold_storm
cold_storm
Im a beginner C programmer, and I was wondering this. Suppose you had a statement that found the length of a string pointed to by the return value from another function. Like this: int material_data_length = strlen(ParseSvTag(temp.value, "\"", "mesh {")); ParseSvTag() returns a pointer to a string that was allocated using malloc(). So my question is what happens to the memory pointed to by the return value of ParseSvTag? Is it lost? Thank you.
Zipster
Zipster
Yeah, unfortunately the pointer is lost, and so that memory just remains allocated. You need to grab that pointer in a separate expression, and then free it when you're done.
cold_storm
cold_storm
thanks. that is what i thought, but i could not find anything in my book or online specifically confirming that. so this is what i should do instead, for example?

char *temp_string = ParseSvTag(temp.value, "\"", "mesh {");
int material_data_length = strlen(temp_string);
free(temp_string);
outRider
outRider
Yes, that will work.

Consider putting that sequence in it's own function, which relieves you from having to remember to free the returned pointer:

int ParseSvTag(whatever_type a, const char *b, const char *c){	char *temp_string = ParseSvTag2(a, b, c);	int material_data_length = strlen(temp_string);	free(temp_string);	return material_data_length;}
JohnBolton
JohnBolton
Functions that return pointers to objects that they allocate can cause problems. The chances of creating a memory leak is high. The user must be very aware that it is the resposibility of the caller to deallocate the returned object. Of course, it isn't possible to avoid these kind of functions completely because this is exactly what new and malloc do.

One way to manage it is to use std::auto_ptr. Instead of returning a pointer to an allocated object, you return a std::auto_ptr.
    std::auto_ptr<Foo> FooFactory()    {        ...        Foo * p = new Foo;        ...        return std::auto_ptr<Foo>( p );    } 
If the object created by FooFactory is not saved by the code that calls the function, then it will be automatically deleted.

Note that you can't do this with arrays. The equivalent for an array of objects would be to return a std::vector (or for character strings, return a std::string).
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Aardvajk
Aardvajk
You'd be better off in C having ParseSvTag2 take a pointer to some memory that the user of the function has allocated, and operate on that.

void ParseSvTag2(char *buffer,int max){    operate_on(buffer,max);}void f(){    char *c=(char*)malloc(1024);    ParseSvTag2(c,1024);    use_result(c);    free(c);}


The user is then free to pass in a statically allocated array, some dynamically allocated data or whatever they want and since they were responsible for allocating it, they are less likely to forget to free it.
cold_storm
cold_storm
thank you, everyone. i believe i will implement EasilyConfused's method.
Xai
Xai
Yes, I find that with the exception of functions named "CreateX" or something similar - you should rarely be creating objects and returning ownership back to the client code.

Letting the client pass you the object to operate on is the first solution (EasilyConfused's) ... and is also the way C++ member functions work (the "this" pointer is the address of a set of memory for the operation to use).

Another option - FOR SPECIAL CASES ... is to have the function create memory and attach it to some collection (as well as return it) so that it won't be lost. This option is usually used ONLY for sets of related functions meant to be used together .. for instance if you wrote a chunking XML parser it would likely have somethintg like this:

XmlParserInit();

while(GetChunk(chunk))
XmlParseChunk(chunk);

//do stuff with chunks

XmlParserCleanup();

----
Basically this is just a hacky way to be lazy and not pass a member pointer when you have singleton symantics. In fact I really almost never use it anymore (but many C APIs do) - I personally prefer member / instance symantics - even in C.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.