C usando gratis correctamente
Frecuentes
Visto 263 veces
1
I believe I am doing this right but wanted to make sure. In a program I am using two pointers that point to allocated memory returned by a function. When I finish using that memory I free()
it, but then I use those same pointers to point at a new allocated memory space. Here is my program to give an example of what I mean (Commented to show my thought process):
int main(void)
{
char *data, *url;
int i = 1;
while(i)
{
printf("Enter URL: ");
if(!(url = getstr())) return 1; //url now points to allocated memory from getstr();
if(strlen(url) <= 0) i = 0;
if(data = readsocket(url, 80, "http")) printf("\n%s\n\n", data); //data now points to allocated memory from readsocket();
else printf("\n\n");
free(url); //free allocated memory that url points to url
free(data); //free allocated memory that data points to data
}
return 0;
}
Is this correct, or is there a better more generally preffered method of doing this? Or am I just completely doing it wrong?
4 Respuestas
5
Assuming your functions getstr
y readsocket
malloc the memory internally then this is perfectly fine.
My only suggestion is that it's often helpful to allocate memory in the same scope that you free it, this often helps reason about when things need to be freed.
Por ejemplo:
url = malloc(URL_MAX_LEN);
if (!url) return 1;
if (!getstr(url)) {
free(url);
return 1;
}
/* do something with url */
free(url);
It can be nice to do this using goto, if you have lots of objects and exit points.
object1 = malloc(OBJECT1_SIZE);
/* do work, if there's an error goto exit1 */
object2 = malloc(OBJECT2_SIZE);
/* do work, if there's an error goto exit2 */
object3 = malloc(OBJECT3_SIZE);
/* do work, if there's an error goto exit3 */
exit3:
free(object3);
exit2:
free(object2);
exit1:
free(object1);
return 1;
If your objects get more complex and require a lot of work to create and destroy then you can wrap malloc and free, but it's critical you apply exactly the same rules to your create/destroy functions as you would to malloc/free to avoid leaks. As a matter of good practice you should always have a destroy to match a create, even if it just wraps free. It's much harder to go wrong that way.
struct x *create_x() {
struct x *p = malloc(10);
p->val1 = 7;
return p;
}
void destroy_x(struct x *p) {
free(p);
}
Respondido 28 ago 12, 17:08
As a general guideline, I propose C's Regla de tres: malloc
, goto
y free
should always come together, or not at all. - Kerrek SB
I this rule is good, but it prevents you from having "factory functions" which create new objects. If you want to use that pattern, you should do one or both of the following: (a) invent consistently name the factory functions (new_XYZ and create_XYZ are good conventions), so that you get in the habit of free()ing them. (b) define a matching "destroy_XYZ" function for each new_XYZ, which might or might not be a simple wrapper for free(). - Adrián Ratnapala
@KerrekSB Or you should forget about goto and write an inline function cleanup() which frees all malloc:ed memory. It is perfectly safe to pass a null pointer as parameter to malloc so the clean up function can look the same no matter from where it is called. - Lundín
@AdrianRatnapala: That's true. There's a somewhat transitive gotcha to the rule, I suppose: You pueden leak one surplus malloc
, but that in turn makes your entire function count as a malloc
-type function itself, which then becomes subject to the Rule... if that makes any sense :-) - Kerrek SB
@AdrianRatnapala I very much agree with this. I'm going to update my answer to include a reference to factory functions. - jleahy
2
If the functions getstr
y readsocket
allocates memory using e.g. malloc
then it's what you are doing is okay.
Respondido 28 ago 12, 14:08
Freeing a NULL pointer is legal C and should have no negative consequences - obviously getting a null back might be a sign of other problems but by itself free(NULL); isn't an error. - Nigel Harper
@KerrekSB I still remember when bad stuff happened, and seem to forget that apparently it's okay these days. - Algún tipo programador
@JoachimPileborg: In soviet Russia, null deletes tí! - Kerrek SB
1
Here's some things I've noticed:
Estas usando
i
to control the loop, but when you seti = 0
, the program has to go all the way to closing curly bracket. I'd recommend usingwhile (1)
ybreak
statements and getting rid ofi
variable:while(1) { ... if (strlen(url) <= 0) break; ... }
Tu estas usando
if (data = readsocket(url, 80, "http"))
which is not technically wrong, but it is a bit misleading as someone may mistake it for comparisonif (data == readsocket(url, 80, "http")
. This is almost a "pattern" in C programming and it's generally a good idea to write just like you did onif (!url = getstr()))
línea:if ((data = readsocket(url, 80, "http")) != NULL) ...
or
if (!(data = readsocket(url, 80, "http"))) ...
this is more a "style"-related, but it is better to write separate statements on separate lines, so don't write
if (!(url = getstr())) return 1
sino más bien
if (!(url = getstr())) return 1;
as for free-ing memory, you're doing just fine
Respondido 28 ago 12, 14:08
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c memory free or haz tu propia pregunta.
¿Cuáles son las semánticas de
readsocket
? - Kerrek SBIt retrieves data from a socket - Keith Miller
A small tip,
strlen
will never return a negative number. - Some programmer dudeI meant what does it return, how does it fail, etc. I'm worried that
free(data)
may be a problem. - Kerrek SBOK, then you're fine. Freeing
NULL
is perfectly legit. - Kerrek SB