Correct use of malloc

  • Thread starter idkfaidkfaidkfa
  • Start date
I

idkfaidkfaidkfa

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
 
N

Nobody

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().
 
J

James Kuyper

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).
 
E

Eric Sosman

[...]
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().
 
J

James Kuyper

[...]
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.
 
J

James Kuyper

[...]
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.
 
M

Malcolm McLean

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.
 
E

Eric Sosman

[...]
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.
 
J

James Kuyper

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.
 
M

Malcolm McLean

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top