Jump to content
  • Advertisement
Sign in to follow this  
_Sigma

[C] pointers,free and NULL

This topic is 3788 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've just been helping my girlfriend with a basic C assignment. However, I'm not sure why something isn't working. The assignment was to make a DVD structure assign a name, etc to it, at which point they were supposed to free it. So basic code:
DVD* myDVD = NULL;

//Create a new DVD called myDVD
myDVD = createDVD();

//set the price and title from a file

//destroy dvd
destroyDVD(myDVD);

The above reference functions are:
DVD* createDVD()
{
	DVD* myDVD = (DVD*)malloc(sizeof(DVD));
	(*myDVD).title = NULL;
	(*myDVD).price = NULL;
	(*myDVD).numViewed = 0;
	return myDVD;
}

void destroyDVD(DVD* name)
{
	free((*name).title);
	free((*name).price);
	(*name).numViewed = 0;
	free(name);
	
	printf("DVD has now been destroyed.\n");	

	name = NULL;
}

The name->title and name->price get malloc'ed in a coiuple other functions, which all work. my question is why name = NULL; doens't actually set myDVD to be NULL...I was under the impression that passing by pointer counted as passing by reference?

Share this post


Link to post
Share on other sites
Advertisement
You pass a pointer (myDVD) by value. However, the pointee can be referenced using the copy of the pointer (name). You cannot modify the pointer variable in the calling function(myDVD), without making a pointer to a pointer.

Share this post


Link to post
Share on other sites
You're passing a copy of the pointer into the function. If you want to modify the original pointer then you need to pass a reference to the original pointer

void func(foo *& refToPtr)
{
etc...
}

Share this post


Link to post
Share on other sites
Good point. In which case you need to either pass the address of the pointer in or just set it to NULL externally.

void Destroy(_type **ppPtr)
{
if( *ppPtr)
{
free(*ppPtr);
*ppPtr = 0;
}
}

Share this post


Link to post
Share on other sites
Here's your code with a couple of revisions/comments (I don't use C much these days, so I can't absolutely guarantee correctness here):

DVD* myDVD = NULL;

/* ... */

myDVD = createDVD();

/* ... */

destroyDVD(&myDVD);

/* ... */

DVD* createDVD()
{
DVD* myDVD = (DVD*)malloc(sizeof(DVD));
/* Note use of -> operator */
myDVD->title = NULL;
myDVD->price = NULL;
myDVD->numViewed = 0;
return myDVD;
}

/* 'name' seems to be an odd choice for the argument name here.
How about 'dvd'? */

void destroyDVD(DVD** name)
{
assert(name);
assert(*name);

free((*name)->title);
free((*name)->price);

/* '*name' is about to be freed, so there's no need to
reset the 'numViewed' field here. */

/*(*name)->numViewed = 0;*/
free(*name);

printf("DVD has now been destroyed.\n");

*name = NULL;
}

Share this post


Link to post
Share on other sites
There seems to be just one last thing to comment on. In C casting the return value of malloc is not required and considered bad practice(or worse). From the horses mouth:
Quote:

142(§6.5, toward the end): The remark about casting the return value of malloc ("the proper method is to declare ... then explicitly coerce") needs to be rewritten. The example is correct and works, but the advice is debatable in the context of the 1988-1989 ANSI/ISO standards. It's not necessary (given that coercion of void * to ALMOSTANYTYPE * is automatic), and possibly harmful if malloc, or a proxy for it, fails to be declared as returning void *. The explicit cast can cover up an unintended error. On the other hand, pre-ANSI, the cast was necessary, and it is in C++ also.

Share this post


Link to post
Share on other sites
Quote:
/* Note use of -> operator */

Yes, she was taught to use the (*varName).xxx which I find really strange too. Since I just cut and copied code...

Quote:
/* 'name' seems to be an odd choice for the argument name here.
How about 'dvd'? */
Yes I know...However that's what she wanted O_o.

Quote:
C++ references (using &) are not available in C.

Reeealllyy.....That explains a lot. I thought I was just drunk or something when it didn't work!

Quote:

You pass a pointer (myDVD) by value. However, the pointee can be referenced using the copy of the pointer (name). You cannot modify the pointer variable in the calling function(myDVD), without making a pointer to a pointer.

...


void Destroy(_type **ppPtr)
{
if( *ppPtr)
{
free(*ppPtr);
*ppPtr = 0;
}
}

Thanks guys.

Cheers

Share this post


Link to post
Share on other sites
Just a note on style: the usual way to use malloc in C is to use var = malloc(sizeof *var) instead of mentioning the type explicitly. This is one less place where the type has to be correct, one less place where errors can occur in your code. (Also as mentioned, in C code the cast should be removed).

So instead of

DVD* myDVD = (DVD*)malloc(sizeof(DVD))


use

DVD* myDVD = malloc(sizeof *DVD);


Hmm, first post. :)

[Edited by - gsg on February 6, 2008 5:29:01 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!