Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Correct use of malloc

Reply
Thread Tools

Correct use of malloc

 
 
idkfaidkfaidkfa@gmail.com
Guest
Posts: n/a
 
      04-09-2013
Hi,
do you think that this is a correct use of malloc function?

void foo(void)
{
.....
prt++;
}

void main()
{
int *ptr=malloc(5*sizeof(int));
....
foo();
free(ptr);
}

Can i use ptr in foo() function without passing it?
Thanks


 
Reply With Quote
 
 
 
 
Nobody
Guest
Posts: n/a
 
      04-09-2013
On Tue, 09 Apr 2013 04:59:46 -0700, idkfaidkfaidkfa wrote:

> do you think that this is a correct use of malloc function?
>
> void foo(void)
> {
> ....
> prt++;
> }
>
> void main()
> {
> int *ptr=malloc(5*sizeof(int));
> ....
> foo();
> free(ptr);
> }
>
> Can i use ptr in foo() function without passing it?


You don't declare "prt" anywhere. Assuming that you meant "ptr", it's
local to main(), so you can't reference it outside main(). And if it was a
global variable, incrementing it within foo() would mean that you can't
pass it to free() as it no longer contains the value returned from the
call to malloc().

 
Reply With Quote
 
 
 
 
James Kuyper
Guest
Posts: n/a
 
      04-09-2013
On 04/09/2013 07:59 AM, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Hi,
> do you think that this is a correct use of malloc function?


No, for several reasons, detailed below.

> void foo(void)
> {
> ....
> prt++;


I assume that was intended to be ptr++.

> }
>
> void main()


Conforming implementations of C are not required to accept main() being
declared as returning void. Many books have been written as if this were
a good idea; if you have such a book, and are free to choose to use a
different book, do so - there's no telling how many other bad habits
that book may be teaching you. Many compilers have been designed to
accept it, but you should not use it. You should always declare main()
as returning int.

> {
> int *ptr=malloc(5*sizeof(int));


It's generally better to use sizeof *ptr. That way, if at some point in
the future you decide to change the type that ptr points at, you only
need to change the type in one location.

If the declaration of ptr is in a different location than the place
where you call malloc() (an issue that will become important down below)
then it's even more important to use this method. Given the following
statement:

car_list = malloc(num_cars * sizeof *car_list);

The fact that the correct size is being referred to can determined just
by looking at that one statement. If you use sizeof(type), you must also
look at the declaration of car_list to make sure that it's the size of
the right type.

You should always check whether malloc() returns a null pointer. If it
does, it means that malloc() failed, and the behavior of a program that
dereferences a null pointer is undefined.

> ....
> foo();
> free(ptr);
> }
>
> Can i use ptr in foo() function without passing it?
> Thanks


No. C variables can only be accessed by name within their scope. The
scope of ptr starts immediately after the "ptr" in it's declaration in
main(), and extends all the way to the '}' that ends the body of main()
- but it does not include functions that are called from within main().
The other issues I'm raising in this message are just a matter of "best
practices"- you'll often get away with writing code this sloppy - but
that's not the case here. You simply cannot use ptr that way.

Passing the pointer value as an argument to foo() is the single best way
to deal with this issue. However, on rare occasions that might not be
possible, such as when writing callback functions with a fixed
interface, such as the comparison functions used by qsort() or
bsearch(). If that's the case, one alternative is to use a file scope
variable, which can be used anywhere in the same file below the the
point where it's declared:

int *ptr;

void foo(void)
{
...
ptr++;
}

int main()
{
ptr = malloc(5*sizeof *ptr);
if(ptr)
{
foo();
free(ptr);
ptr = NULL;
}
return 0;
}

When you free() a piece allocated memory, all pointers that used to
refer to any part of that memory have indeterminate values. That means
that you cannot safely use them for ANY purpose, not even checking them
for equality with another pointer value. If there's any chance that a
pointer object might be used again after you free the memory it refers
to, you should re-set it to a null value, which can at least be safely
checked for equality. The code which uses that value can check whether
it's null, and use that fact to avoid doing anything else with it. In
this particular case, it's easy to see that ptr will never be used again
- but I make it a habit to always null such pointers unless the pointer
object's lifetime is guaranteed to end before the very next statement
gets executed; ptr's lifetime continues after the return statement is
executed (though not for very long after that point).

Explicitly returning 0 from main() is not strictly necessary; special
rules were added to C99 to allow it. However, those special rules were a
concession to a popular piece of bad programming - it's a bad idea to
take advantage of those rules. You should develop a habit of always
making sure that any function declared as returning a value does in fact
return a value (unless you're certain that the value will not be used -
but the value returned by the initial call to main() in a program is
always used).
--
James Kuyper
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      04-09-2013
On 4/9/2013 11:29 AM, James Kuyper wrote:
> [...]
> int *ptr;
>
> void foo(void)
> {
> ...
> ptr++;
> }
>
> int main()
> {
> ptr = malloc(5*sizeof *ptr);
> if(ptr)
> {
> foo();
> free(ptr);


Undefined behavior here, because `ptr' is no longer the
value returned by malloc(): It was modified by foo().


> ptr = NULL;
> }
> return 0;
> }


--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      04-09-2013
On 04/09/2013 11:48 AM, Eric Sosman wrote:
> On 4/9/2013 11:29 AM, James Kuyper wrote:
>> [...]
>> int *ptr;
>>
>> void foo(void)
>> {
>> ...
>> ptr++;
>> }
>>
>> int main()
>> {
>> ptr = malloc(5*sizeof *ptr);
>> if(ptr)
>> {
>> foo();
>> free(ptr);

>
> Undefined behavior here, because `ptr' is no longer the
> value returned by malloc(): It was modified by foo().


You're right - I mistakenly copied that mistake from the original code.
Having so many mistakes in a single piece of code is pretty impressive
(and possibly suspicious).

The simple fix is free(ptr-1). However, in the more general case, a
program like this really should have two separate variables: one that
contains the value returned by malloc(), which should never be changed,
and should be passed to free() when you're done with it. A separate
variable should be used to keep track of a particular place within the
allocated array.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      04-09-2013
On 04/09/2013 11:48 AM, Eric Sosman wrote:
> On 4/9/2013 11:29 AM, James Kuyper wrote:
>> [...]
>> int *ptr;
>>
>> void foo(void)
>> {
>> ...
>> ptr++;
>> }
>>
>> int main()
>> {
>> ptr = malloc(5*sizeof *ptr);
>> if(ptr)
>> {
>> foo();
>> free(ptr);

>
> Undefined behavior here, because `ptr' is no longer the
> value returned by malloc(): It was modified by foo().


You're right - I mistakenly copied that mistake from the original code.
Having so many mistakes in a single piece of code is pretty impressive
(and possibly suspicious).

The simple fix is free(ptr-1). However, in the more general case, a
program like this really should have two separate variables: one that
contains the value returned by malloc(), which should never be changed,
and should be passed to free() when you're done with it. A separate
variable should be used to keep track of a particular place within the
allocated array.
--
James Kuyper
 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      04-09-2013
On Tuesday, April 9, 2013 12:59:46 PM UTC+1, (E-Mail Removed) wrote:
> Hi,
>
> do you think that this is a correct use of malloc function?
>
> void foo(void)
> {
>
> ....
>
> prt++;
>
> }
>
>
> void main()
> {
> int *ptr=malloc(5*sizeof(int));
>
>
> foo();
>
> free(ptr);
> }
>
>
> Can i use ptr in foo() function without passing it?
>

You can make ptr global, then foo can operate on it. But, as others have
said, if you increment it you have to decrement it again before freeing
it.
Generally both of these things are a bad idea. Allocate as much space as
you need in a high level function, pass the pointer to your lower
level functions, and the free it in the high level function. Globals
should be rare.

The problem with malloc, and pointers generally, is that it's hard to
show correct use in small snippets of code. Pointers come into their
own with real problems where N depends on input data.


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      04-09-2013
On 4/9/2013 11:56 AM, James Kuyper wrote:
> On 04/09/2013 11:48 AM, Eric Sosman wrote:
>> On 4/9/2013 11:29 AM, James Kuyper wrote:
>>> [...]
>>> int *ptr;
>>>
>>> void foo(void)
>>> {
>>> ...
>>> ptr++;
>>> }
>>>
>>> int main()
>>> {
>>> ptr = malloc(5*sizeof *ptr);
>>> if(ptr)
>>> {
>>> foo();
>>> free(ptr);

>>
>> Undefined behavior here, because `ptr' is no longer the
>> value returned by malloc(): It was modified by foo().

>
> You're right - I mistakenly copied that mistake from the original code.
> Having so many mistakes in a single piece of code is pretty impressive
> (and possibly suspicious).
>
> The simple fix is free(ptr-1). However, in the more general case, a
> program like this really should have two separate variables: one that
> contains the value returned by malloc(), which should never be changed,
> and should be passed to free() when you're done with it. A separate
> variable should be used to keep track of a particular place within the
> allocated array.


I'm sure *you* knew that, but I pointed it out because I
wasn't sure "idkfaidkfaidkfa" does. (If "idkfaidkfaidkfa"
cares, that is.)

However, the need in cases like this to maintain multiple
pointers to (or into, or near) an allocated block somewhat
diminishes the value of NULL'ing a pointer variable after
free(). You can zap the particular variable that supplied
the value for the free() call, but finding and zapping other
related variables will not always be possible. NULL'ing the
proximate variable doesn't hurt, of course, but if it confers
a feeling of safety I fear the feeling is unfounded. It may
be better to know you're unarmored than to put too much faith
in a chiffon shield.

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      04-09-2013
On 04/09/2013 01:06 PM, Eric Sosman wrote:
....
> However, the need in cases like this to maintain multiple
> pointers to (or into, or near) an allocated block somewhat
> diminishes the value of NULL'ing a pointer variable after
> free(). You can zap the particular variable that supplied
> the value for the free() call, but finding and zapping other
> related variables will not always be possible.


Well, the rule I apply in that case requires that all such variables be
nulled, if possible, unless their lifetime is about to end, anyway.

> ... NULL'ing the
> proximate variable doesn't hurt, of course, but if it confers
> a feeling of safety I fear the feeling is unfounded. ...


If, for any reason, it's not possible to null all of the relevant
pointers, believe me, "safe" is not what I'm feeling.
 
Reply With Quote
 
Malcolm McLean
Guest
Posts: n/a
 
      04-10-2013
On Tuesday, April 9, 2013 6:41:32 PM UTC+1, James Kuyper wrote:
> On 04/09/2013 01:06 PM, Eric Sosman wrote:
>
>
> > However, the need in cases like this to maintain multiple
> > pointers to (or into, or near) an allocated block somewhat
> > diminishes the value of NULL'ing a pointer variable after
> > free(). You can zap the particular variable that supplied
> > the value for the free() call, but finding and zapping other
> > related variables will not always be possible.

>
>
> Well, the rule I apply in that case requires that all such variables be
> nulled, if possible, unless their lifetime is about to end, anyway.
>

The rule I apply is that you either have matching mallocs and frees,
with the frees almost always the last statements in the function,
or if this isn't possible because you are creating a tree or similar
structure, you have a constructor / destructor function set up.

So I don't worry about aliases to the pointers in local variables.

There might be situations where this pattern can't be followed,
but they are few and far between. I do find it's more important
to null pointers before allocation, so if an allocation fails, it's
easier to free the rest neatly.
--
Malcolm's webpage, lots of C programming resources
http://www.malcolmmclean.site11.com/www
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
to malloc or not to malloc?? Johs32 C Programming 4 03-30-2006 10:03 AM
porting non-malloc code to malloc micromysore@gmail.com C Programming 3 02-19-2005 05:39 AM
Malloc/Free - freeing memory allocated by malloc Peter C Programming 34 10-22-2004 10:23 AM
free'ing malloc'd structure with malloc'd members John C Programming 13 08-02-2004 11:45 AM
Re: free'ing malloc'd structure with malloc'd members ravi C Programming 0 07-30-2004 12:42 PM



Advertisments