can i access 'p' even after free(p);

H

Hassan Iqbal

hi,
in the code below i find that i am able to access p even after i have
freed it.
not only that the previous values stored in p are accessible even
after reallocation of memory to p. please some one explain it to me.
what does malloc and free do here?
thanks,
hassan

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

main()
{
int i,n,*p;
printf("\n give value for n: ");
scanf("%d", &n);

p= (int *)malloc(n*sizeof(int ));
printf("\n give %d integers: ", n);
for(i=0;i<n;i++){
printf("\nReadig int...");
scanf("%d", (p+i));
printf("\nThe value is %d ", *(p+i));
}
printf("\n the given integers are: ");
free(p);
p= (int *)malloc(n*sizeof(int ));
for(i=0;i<n;i++)
printf("%d ", *(p+i));
//free(p);
printf("\n\n");
return 0;
}
 
A

Andreas Kahari

hi,
in the code below i find that i am able to access p even after i have
freed it.
not only that the previous values stored in p are accessible even
after reallocation of memory to p. please some one explain it to me.
what does malloc and free do here?
thanks,
hassan

See the FAQ here:
http://www.eskimo.com/~scs/C-faq/q7.20.html

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

main()

main() should always be explicitly declared as returning int.

{
int i,n,*p;
printf("\n give value for n: ");
scanf("%d", &n);

p= (int *)malloc(n*sizeof(int ));
printf("\n give %d integers: ", n);
for(i=0;i<n;i++){
printf("\nReadig int...");
scanf("%d", (p+i));
printf("\nThe value is %d ", *(p+i));
}
printf("\n the given integers are: ");

Strange convention to always output the newline in the beginning
of the string...

free(p);
p= (int *)malloc(n*sizeof(int ));

Don't cast the return value of malloc().

for(i=0;i<n;i++)
printf("%d ", *(p+i));

Accessing uninitialized memory here.



Cheers,
Andreas
 
J

Joona I Palaste

Hassan Iqbal said:
hi,
in the code below i find that i am able to access p even after i have
freed it.
not only that the previous values stored in p are accessible even
after reallocation of memory to p. please some one explain it to me.
what does malloc and free do here?
thanks,
hassan

Accessing free()d memory causes undefined behaviour. This means that
the implementation is free (pun not intended) to do ANYTHING AT ALL.
Some of the things it can do is:
1) Access the memory normally as if nothing had happened.
2) Segfault.
3) Corrupt your HD's master file system.
4) Call the local police office and tell them you're smuggling crack.
5) Make pink fluffy elephants dance on your desktop.
You might be experiencing behaviour number 1. This is possible for
your system but not guaranteed for all systems. This is precisely the
point of undefined behaviour.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
main()
{
int i,n,*p;
printf("\n give value for n: ");
scanf("%d", &n);
p= (int *)malloc(n*sizeof(int ));

printf("\n give %d integers: ", n);
for(i=0;i<n;i++){
printf("\nReadig int...");
scanf("%d", (p+i));
printf("\nThe value is %d ", *(p+i));
}
printf("\n the given integers are: ");
free(p);
p= (int *)malloc(n*sizeof(int ));

You are reassigning more malloc()ed memory to p. This means that
when you use p below, it has NOTHING AT ALL to do with the memory
you just free()d. It only has the same name, but different contents.
for(i=0;i<n;i++)
printf("%d ", *(p+i));
//free(p);
printf("\n\n");
return 0;
}

What your problem seems to be is that you're assigning some sort of
mystical significance to reassignment of pointer values. Your program
is essentially a more complicated version of:

int main(void) {
int p;
p=1;
p=2;
return 0;
}

and expecting the assignment "p=2" to fail because you're trying to
assign "1=2".

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"As we all know, the hardware for the PC is great, but the software sucks."
- Petro Tyschtschenko
 
D

Darrell Grainger

hi,
in the code below i find that i am able to access p even after i have
freed it.
not only that the previous values stored in p are accessible even
after reallocation of memory to p. please some one explain it to me.

Accessing a pointer after a call to free() is undefined behaviour. This
means that anything can happen. It could format your hard drive, cause
world peace, have nasal demons fly out your nose, or... it could work as
if you never called free(). The point is that since you cannot guarantee
what will happen, it is best to avoid undefined behaviour.
what does malloc and free do here?

It tells the system that it CAN destroy the data p pointed to. The system
will probably do nothing until it needs the free memory but you cannot
guarantee that.
thanks,
hassan

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

main()

int main(void)
{
int i,n,*p;
printf("\n give value for n: ");
fflush(stdout);

scanf("%d", &n);

What if the user inputs "two" or "ha ha, crashed your program." You should
be checking the results.
p= (int *)malloc(n*sizeof(int ));

Why are you casting the result from malloc? This is a guaranteed way to
hide when you forgot to #include <stdlib.h>. There is absolutely no reason
you should be casting the result from malloc.

Did the malloc work? Or is p == NULL? Might want to check that.
printf("\n give %d integers: ", n);
fflush(stdout);

for(i=0;i<n;i++){
printf("\nReadig int...");

printf("\nReading int...");
fflush(stdout);
scanf("%d", (p+i));
printf("\nThe value is %d ", *(p+i));
fflush(stdout);

}
printf("\n the given integers are: ");
fflush(stdout);

free(p);
p= (int *)malloc(n*sizeof(int ));
for(i=0;i<n;i++)
printf("%d ", *(p+i));

Undefined what this is going to print out. It is luck that you got the
original data back.
//free(p);
printf("\n\n");
return 0;
}

--
darrell at cs dot toronto dot edu
or
main(){int j=1234;char t[]=":mad:abcdefghijklmnopqrstuvwxyz.\n",*i=
"iqgbgxmdbjlgdv.lksrqek.n";char *strchr(const char *,int);while(
*i){j+=strchr(t,*i++)-t;j%=sizeof t-1;putchar(t[j]);} return 0;}
 
R

Richard Bos

Ning said:
Hi. I read the faq. The only thing I can find about casting pointer returned
from malloc() is
"Under ANSI/ISO Standard C, these casts are no longer necessary."
in http://www.eskimo.com/~scs/C-faq/q7.7.html

I wonder if there is any drawbacks of casting a (void*) pointer to a
specific type it is assigned to?

Apart from every unnecessary call, no matter what kind, being an
abomination, and evil in the eye of the Compiler, you mean? Well, for
starters you'll be sorry if you ever change the type of p.

Richard
 
R

Richard Bos

Ning said:
1. ANSI C use (void *) as a generic pointer type, and no cast is necessary
is necessary when a (void*) is assigned to a pointer to any particular type.

2. malloc() is declared in stdio.h. It returns a (void*) and it is
guaranteed
to be aligned properly so it can be assigned to a pointer to any type.

3. If stdio.h is not #included or properly declared, malloc() is view as a
function with an int return value, so there will be a problem when I write
int *p; p = malloc( sizeof(int) );

Almost. For the first point, void * can be assigned to any kind of
_object_ pointer, but not to function pointers. For the second and
not in <stdio.h>. Otherwise said:
And one more thing. The course project I am working on comes with an
example program that we can fill the blanks in. It uses calloc() but instead
of stdio.h, it #includes <malloc()>. Is <malloc.h> a header file in ANSI
standard?

No. calloc(), like malloc(), realloc() and free(), is in <stdlib.h>.
BTW, calloc() is usually not the right function to use.

Richard
 
N

Ning

Andreas Kahari said:
Don't cast the return value of malloc().

Hi. I read the faq. The only thing I can find about casting pointer returned
from malloc() is
"Under ANSI/ISO Standard C, these casts are no longer necessary."
in http://www.eskimo.com/~scs/C-faq/q7.7.html

I wonder if there is any drawbacks of casting a (void*) pointer to a
specific
type it is assigned to?
 
N

Ning

Joona I Palaste said:
Because you have #included <stdlib.h>, it is safe to drop the cast.

Hi, guys. I am new to C. Although I have read the faq, but I am not sure
I get the void pointer stuff. So could you read on and see if what I say is
correct?

So what Joona said means:
1. ANSI C use (void *) as a generic pointer type, and no cast is necessary
is necessary when a (void*) is assigned to a pointer to any particular type.

2. malloc() is declared in stdio.h. It returns a (void*) and it is
guaranteed
to be aligned properly so it can be assigned to a pointer to any type.

3. If stdio.h is not #included or properly declared, malloc() is view as a
function with an int return value, so there will be a problem when I write
int *p; p = malloc( sizeof(int) );

And one more thing. The course project I am working on comes with an
example program that we can fill the blanks in. It uses calloc() but instead
of stdio.h, it #includes <malloc()>. Is <malloc.h> a header file in ANSI
standard?

Thanks.
 
A

Andreas Kahari

Hi. I read the faq. The only thing I can find about casting pointer returned
from malloc() is
"Under ANSI/ISO Standard C, these casts are no longer necessary."
in http://www.eskimo.com/~scs/C-faq/q7.7.html

I wonder if there is any drawbacks of casting a (void*) pointer to a
specific
type it is assigned to?

Yes, you need to type more. Then, when you change the type of
p, you need to remember to change in more places.

The preferred code would look like

p = malloc(n*sizeof *p);

.... which is independent of the type of p.

See also
http://users.powernet.co.uk/eton/c/hackerhotel.html
http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1047673478&id=1043284351
 
N

Ning

Richard Bos said:
Almost. For the first point, void * can be assigned to any kind of
_object_ pointer, but not to function pointers. For the second and
third, malloc() is declared in <stlib.h>, not in <stdio.h>. Otherwise,
you've got it right.

Oh. That said:
No. calloc(), like malloc(), realloc() and free(), is in <stdlib.h>.
BTW, calloc() is usually not the right function to use.

Why is calloc() not right? Because it fills with 0's in all bits and might
make
programmer forget to initialize the allocated memory properly?

Ning
 
D

Darrell Grainger

Hi. I read the faq. The only thing I can find about casting pointer returned
from malloc() is
"Under ANSI/ISO Standard C, these casts are no longer necessary."
in http://www.eskimo.com/~scs/C-faq/q7.7.html

I wonder if there is any drawbacks of casting a (void*) pointer to a
specific
type it is assigned to?

Yes. The following program has a problem. The cast is hiding it:

#include <stdio.h>
#define SIZE 10

int main(void)
{
int i;
int *p = (int *)malloc(SIZE*sizeof *p);
if(p == NULL)
return 1;

for(i = 0; i < 10; i++) {
p = i;
printf("%d\n", p);
}

free(p);
return 0;
}

The failure to #include <stdlib.h> will make the compiler unaware that
malloc returns (void *) but the cast will hide the warning messages on
many compilers.

--
darrell at cs dot toronto dot edu
or
main(){int j=1234;char t[]=":mad:abcdefghijklmnopqrstuvwxyz.\n",*i=
"iqgbgxmdbjlgdv.lksrqek.n";char *strchr(const char *,int);while(
*i){j+=strchr(t,*i++)-t;j%=sizeof t-1;putchar(t[j]);} return 0;}
 
D

Darrell Grainger

Hi, guys. I am new to C. Although I have read the faq, but I am not sure
I get the void pointer stuff. So could you read on and see if what I say is
correct?

So what Joona said means:
1. ANSI C use (void *) as a generic pointer type, and no cast is necessary
is necessary when a (void*) is assigned to a pointer to any particular type.
Correct.

2. malloc() is declared in stdio.h. It returns a (void*) and it is
guaranteed
to be aligned properly so it can be assigned to a pointer to any type.

The malloc function requires said:
3. If stdio.h is not #included or properly declared, malloc() is view as a
function with an int return value, so there will be a problem when I write
int *p; p = malloc( sizeof(int) );

If said:
And one more thing. The course project I am working on comes with an
example program that we can fill the blanks in. It uses calloc() but instead
of stdio.h, it #includes <malloc()>. Is <malloc.h> a header file in ANSI
standard?

The functions malloc, calloc, realloc and free require <stdlib.h>. Most
likely, your compiler has <stdlib.h> including <malloc.h>. Some
programmers will #include <malloc.h> because it will save them a few
seconds when compiling. It is faster to #include <malloc.h> than to
#include <stdlib.h> which will then #include <malloc.h>. One file access
is faster than two file accesses. For me, I'd rather be portable than
fast. The computer I work on will take literally a few seconds more. Even
if I compile 100 times a day it is only saving me 2 minutes.

--
darrell at cs dot toronto dot edu
or
main(){int j=1234;char t[]=":mad:abcdefghijklmnopqrstuvwxyz.\n",*i=
"iqgbgxmdbjlgdv.lksrqek.n";char *strchr(const char *,int);while(
*i){j+=strchr(t,*i++)-t;j%=sizeof t-1;putchar(t[j]);} return 0;}
 
D

Dan Pop

I wonder if there is any drawbacks of casting a (void*) pointer to a
specific type it is assigned to?

Yes: if the specific type gets changed later, the cast has to be changed,
too. The cast generates maintenance overhead for no redeeming benefits.

In the specific case of malloc, the cast also disables a useful diagnostic
if the programmer has forgotten to include <stdlib.h>. The following
program doesn't require any diagnostic, despite being broken:

int main()
{
char *p = (char *)malloc(10);
free(p);
return 0;
}

Remove the cast and the compiler *must* complain, because the int value
returned by malloc() is assigned to a pointer.

Dan
 
A

Arthur J. O'Dwyer

Why is calloc() not right? Because it fills with 0's in all bits
and might make programmer forget to initialize the allocated memory
properly?

Well, mostly because it *does* initialize each byte of the allocated
memory to zero. That involves visiting every byte in the allocated
block. That means the time-complexity of memory allocation jumps
from roughly O(1) to O(N), instantly. That's *very* inefficient,
compared to using the regular malloc() for everything.
And since all-bits-zero doesn't have any useful semantic value for
*most* data types, the "initialization" doesn't save the programmer
any time, either.
Additionally, I hate calloc() because it takes two arguments where
one argument would do fine. That's just silly.

-Arthur
 
J

Joona I Palaste

<stdlib.h> :)
Well, mostly because it *does* initialize each byte of the allocated
memory to zero. That involves visiting every byte in the allocated
block. That means the time-complexity of memory allocation jumps
from roughly O(1) to O(N), instantly. That's *very* inefficient,
compared to using the regular malloc() for everything.
And since all-bits-zero doesn't have any useful semantic value for
*most* data types, the "initialization" doesn't save the programmer
any time, either.
Additionally, I hate calloc() because it takes two arguments where
one argument would do fine. That's just silly.

Correct me if I'm wrong here, but what's stopping malloc() from also
initialising every byte to 0? Where does the C standard define any
asymptotic time constraints for any function whatsoever? A malloc()
implementation taking O(N^2) time would be perfectly legal, as long as
it returned a pointer to enough valid memory?

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"I am not very happy acting pleased whenever prominent scientists overmagnify
intellectual enlightenment."
- Anon
 
A

Arthur J. O'Dwyer

Arthur J. O'Dwyer scribbled the following:


Correct me if I'm wrong here, but what's stopping malloc() from also
initialising every byte to 0? Where does the C standard define any
asymptotic time constraints for any function whatsoever? A malloc()
implementation taking O(N^2) time would be perfectly legal, as long as
it returned a pointer to enough valid memory?

Correct. But that's not terribly common, is it? ;-)

-Arthur
 
J

John Bode

Ning said:
Hi. I read the faq. The only thing I can find about casting pointer returned
from malloc() is
"Under ANSI/ISO Standard C, these casts are no longer necessary."
in http://www.eskimo.com/~scs/C-faq/q7.7.html

I wonder if there is any drawbacks of casting a (void*) pointer to a
specific
type it is assigned to?

It will hide a compile-time diagnostic if you don't have a prototype
for malloc() in scope (for example, you forget to #include
<stdlib.h>). Without a prototype in scope, the compiler will assume
that malloc() returns int, not void *. By adding the cast, you will
suppress any type-mismatch diagnostics. Depending on your platform's
calling conventions, this mismatch may lead to subtle runtime
problems.
 
S

Simon H.

I hope you don't mind me butting in, but I have an issue that seems
somewhat related... I'm implementing a variable-length array/stack,
and free() is giving me some interesting issues. It looks something
like this...

---
#include <stdlib.h>
#include <stdio.h>
#include "vararray.h"

/* Just including this for clarity */
void va_init( va_vararray v )
{
v->size = INITIAL_SIZE;
v->index = 0;
v->contents = malloc( INITIAL_SIZE * sizeof( va_ptr ) );
}

int main()
{
va_vararray v;
va_init( v );
printf( "Malloc'd: %x\n", (int) v->contents );
printf( "Doing stuff...\n" );

/* Pushes and pops a few elements as a test --no array-expansion
happening,
yet, no further malloc()'s called. */

printf( "Freeing...\n" );
free( v->contents );
printf( "Freed\n" );

return 0;
}
---

So, simple and straightforward, yes? So one would think, but it
crashes when trying to free the memory. I'm using a Linux system that
is nice enough to let you print debugging messages on malloc() and
free() via an environment variable, so running the program looks
something like this:

---
# export MALLOC_DEBUG_=1
# ./a.out
Malloc'd: 0x123456789ABC
Doing stuff...
Freeing...
free(): invalid address: 0x123456789ABC <--error message from OS
Segmentation fault
---

I've played around with it a bit, and upgraded to the latest version
of gcc, but no dice. Oddly enough, if I try to free() the thing right
after initializing it, it works flawlessly (except for the rest of the
program crashing, of course). So I'm just a tad puzzled here.

Thanks a lot,
Simon
 
I

Irrwahn Grausewitz

I hope you don't mind me butting in, but I have an issue that seems
somewhat related... I'm implementing a variable-length array/stack,
and free() is giving me some interesting issues. It looks something
like this...

---
#include <stdlib.h>
#include <stdio.h>
#include "vararray.h"

/* Just including this for clarity */
void va_init( va_vararray v )
{
v->size = INITIAL_SIZE;
v->index = 0;
v->contents = malloc( INITIAL_SIZE * sizeof( va_ptr ) );

You have just changed the members of a local copy of an va_vararray
struct (whatever it looks like, wherever it has been declared) and
forget everything on return.
}

int main()
{
va_vararray v;
va_init( v );

The contents of v are still indeterminate at this point.

free( v->contents );

And freeing a non-initialized pointer invokes undefined behaviour. If
your program chrashes during testing, you are lucky because you know you
made a mistake. If not, the Space Shuttle may return in several pieces.

<SNIP>

To get it right you have to change va_init() to take a va_vararray* .
BTW: the va_* names are IMHO a bad choice; readers of your code may
confuse them with objects declared in <stdarg.h>.

Regards

Irrwahn
 

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
474,082
Messages
2,570,588
Members
47,209
Latest member
Ingeborg61

Latest Threads

Top