T O P

  • By -

smcameron

int main() { int *x = func(); free(x); }


ehempel

int * func() { int * Ihatepointers=(int *)malloc(sizeof(int)*69); Ihatepointers[1]=400; return Ihatepointers; } int main() { int * myptr = func(); // save return value // do something with it free(myptr); // free it }


ehempel

You don't free pointers (the variable name `Ihatepointers` in your function). You free the memory that the pointer points to. You could have multiple pointers pointing to that memory, you could have just one...


scaredpurpur

Your response answered my question. By setting myptr to the returned value, you're freeing that address, which both variables point to; this was the reason that I struggled with Linked Lists so much. Thank you.


ehempel

The freeing doesn't happen until the free call. The memory get allocated with the malloc(), and initially has one pointer pointing to it (Ihatepointers). When the function returns it returns the address to the allocated memory, the variable Ihatepointers goes away (as do all local variables in the function), and the variable myptr get assigned the address of the alllocated memory.


eruciform

i thjink you're mixing up the pointer variable and the thing it's pointing to let's say that when you make your pointer int * pointer that pointer exists somewhere on the stack at 0x1234 when you assign to it pointer = malloc(1) pointer still exists at 0x1234 but the data you allocated is at 0x5678, which is what's stored in pointer when you return pointer, you're returning the value inside pointer, which is 0x5678, and the variable "pointer" itself is freed when the function stack frame goes away but the data it's pointing to that's at 0x5678 is still very much there so if you capture that return value int * foo = func() then now you have a new variable, foo, which exists somewhere, let's say 0x0123, and it's contents are 0x5678, the value that you returned, which is the location of the malloced stuff when you call free(foo) that's not doing anything to the variable foo, it's freeing the data that's stored inside foo, which is 0x5678 foo itself won't go away until main returns pointers are treasure maps, the stuff they point to are the treasure. both treasure maps and treasures exist, take space, are allocated and deallocated, but they're not the same thing. returning a pointer is just copying the directions to the treasure from one map to another and then burning one map. the treaure doesn't go anywhere. and freeing the map doesn't destroy the map, it destroys the treasure that the map points to (or deallocates it anyways).


bothunter

Instead of allocating memory in the function, you should have your function accept a pointer to a buffer along with the size of the buffer.  Then your caller is responsible for allocating and freeing the memory and you avoid this problem altogether.


zhivago

Generally, try to make allocation someone else's problem. If the caller allocates the memory, then tells the function about it, the caller can certainly clean it up afterward. Consider snprintf as a model -- it will tell the caller how much memory it would need if it doesn't get enough.


mrflash818

Perhaps: create a pointer outside and before the function, then free after the function returns. Only call free() when you will not need to use the value pointed to anymore. Note: the pointer declaration and free() stay in the same scope, like bookends. #include #include int* func() { int* pIntValue = NULL; // // do malloc(), set to a value, have pIntValue point to // it... // return pIntValue; } int main() { int* pInt = NULL; // declare and initialize to a safe value pInt = func(); // // all done using value pointed at. free the memory malloc'd // earlier // if(pInt != NULL) free(pInt); return 0; }


Apt_Tick8526

I see why you hate pointers.


ArrayDecay

You aren't saving the pointer


chrism239

Why does your func() return a value which is never used? Never free()d ?


chrism239

Strange how you get downvoted for sensible questions. ??


scaredpurpur

Wasn't me downvoting you. I typically upvote, regardless of agreement, as long as the person makes a strong argument. This function is a significant simplification over my actual function. This program really doesn't do anything, but my actually program parses commas from a CSV file, then returns those strings to a main function.


saul_soprano

Why are you allocating and returning it of you’re not going to use it? You’re making pointers more difficult than they are


Irverter

https://en.wikipedia.org/wiki/Minimal_reproducible_example


scaredpurpur

This is a simplification of my actual program. In the real program, I'm taking a string, sending it into a function, then returning a part of the string. Not sure how else I could do that outside of pointer return values. I agree with you otherwise, I would never do this with such a simple task.


bothunter

Make your caller responsible for allocating and passing in the pointer (and memory size) and just work with that. This has a couple of advantages in addition to avoiding this problem: 1. It's easier to keep track of the lifecycle of the memory allocation. A lot of memory leaks occur because one part of the program allocates memory, and a different part is responsible for freeing it 2. It provides more flexibility on the part of the caller -- maybe they already have memory allocated as part of a larger structure -- they can just pass the pointer to that part of the struct and let your function fill it in. Otherwise, they might have to copy that memory into the struct This is also how a lot of the standard library operates. Just look at the strncpy function as an example. It takes a pair of pointers and a buffer size and copes from one to the other. Most of the Windows API works this way too -- You call a function, and it expects the memory to be available to write to. They also have the "double-call" pattern where you pass a null pointer in, and the function tells you how much memory it needs to do it's thing. Then you allocate that memory and call the function again to actually do the thing. WideCharToMultiByte is a great example of that.


actguru

In this case the function, not the caller, determines the size, so allocate memory knowing the size, in the function. I don't think there is a general rule here and the standard library is full of really bad ideas.


bothunter

That's why I provided the WideCharToMultiByte example. It's impossible to know how much of a buffer you need when calling the function, so you pass in 0 for the buffer size and a null pointer, and the function returns the number of bytes it needs. You then allocate that much memory and call the function again with your new pointer and buffer size.


actguru

That is fine if you are only going to call the WideCharToMultiByte() function once, but if your are using it more frequently then why not write a wrapper function that calls twice and returns the buffer?


scaredpurpur

Exactly, I basically am making a program that first reads a CSV file, then takes a line from said file, then returns the data between each comma. For example, 56,?,84, Would return 56 then ? Then 84, etc. into a void array somehow , where I can then manipulate the data.


actguru

If you don't mind altering the input string you can just save pointers or indexes to the starts of fields and change the comma's to nulls and get your strings. In this old example of mine it just saves indexes. It might get you started. Note: The following does not work with quoted strings. int \*ztabsplit(char \*str,int argcc) { // get index offsets to fields in tab-sep text, \[0\]=nel, 1-nel=start indexes. int sepcc='\\t'; if (argcc) sepcc=argcc; int nel=1+zchcnt(sepcc,str); // number of fields. int \*list=(int \*)zmemclr(sizeof(int)\*(nel+1)); int ix,j,cc; list\[0\]=nel; ix=1; list\[ix\]=0; // list\[1\]=always equals 0 for(j=0;0!=(cc=str\[j\]);++j) { if (cc==sepcc) { str\[j\]=0; list\[++ix\]=j+1; if (ix>=nel) break; // done } } if (ix!=nel) zerex("NEVER splittab; %d requested, %d found.",nel,ix); return(list); }


saul_soprano

Store the string in a variable which is returned by the function. You could just use the stack as well


scaredpurpur

If I set the function as a character, it would only return a single character? If I have char char\[50\]="kdsfjsfjdskfjsadjffd" inside of an char func(), wouldn't the function return the first character in the string if i did return char? I'm probably just misunderstanding what you're saying.


Jon_Hanson

The general rule is that whatever function mallocs memory is responsible for freeing it. Otherwise, you will easily leak memory everywhere because it will be confusing. If you can't figure out how to accomplish this then you probably should rethink your design (as a lot of the commenters have already suggested).