Friday, November 24, 2006

Dynamic Memory Allocation in C, C++ - my strange experiences with gcc and g++

Yesterday i learnt few strange things about malloc() in C and new, delete operators in C++.
Compiler referred is gcc for C, and g++ for C++ programs.

First one:
int *a=malloc(sizeof(int) *0); //i am trying to allocate 0 bytes of memory and pointing that location with pointer a.
==> What should happen, Segmentation fault( run time error) , since allocating 0 bytes of memory is absurd and then referencing it through a pointer a is too wrong. It went through compilation and run perfectly on 'dereferencing' as a[0]=5, a[1]=2,... .
==> But i get segfault when i am trying to allocate -ve bytes of memory.

Second one:
int *a= new int[0];
==> the same effect with 0 size memory allocation and runtime error when trying to allocate (-ve)size of memory.

Third one:
This one, i strongly beleive that it sould raise runtime error, as it is mentioned in C++ standards.
int* a=new int[10];
......
delete a; //Here it should be delete[] a;
==> When an array of objects are created with new operator, while deleting all objects, we should use delete[], instead of delete; since delete will only delete that object.

Fourth one:
Do you think that on freeing or deleting the dynamic memory, the contents/memory locations will be deleted permanantly? No, it shouldn't be. The compiler will just cut of those associated links and the memory locations still with the content that we have assigned. If u want to try, assign the locations to other pointer before freeing/deleting.
My experience is:
int *a=malloc(sizeof(int)*4);
a[0]=1;a[1]=2;a[2]=3;a[3]=4;
int *t;
t=a;
free(a);
printf("%d , %d , %d , %d ",t[0],t[1],t[2],t[3]);
//Answer is "0 , 2 , 3 , 4"

int *a=new int[4];
a[0]=1;a[1]=2;a[2]=3;a[3]=4;
int *t;
t=a;
delete(a);
printf("%d , %d , %d , %d ",t[0],t[1],t[2],t[3]);

//Answer is "0 , 2 , 3 , 4"

==> I am not able to figure out the logic behind making the value of base address to 0 upon deleting. If it is to make value of deleted location as '0', then it should be with all the locations that are dynamically created. But it isn't. And also one more thing is 'write' operation is more costly than delinking.

Your comments are appreciated, if you have proper reasons.

19 comments:

Anonymous said...

For the 4th one:
After freeing the dynamic memory, the contents at these adress are UNDEFINED. So it can have be anything.

uma said...

@sridhar,
UNDEFINED means, will the contents at that address intentionally change? Why compiler take time to change the contents. though, if changing then it shd put NULL, so that there won't be any 'garbage' concept.

Anonymous said...

The contents at that address might change or might not change. That memory might be allocated and might get changed.
You should not take into consideration how the compiler behaves. You have to consider the language documentation. Each compiler may implement it in different fashion. If you follow according to some compiler then your programs are not portable.

For First One:
The behaviour for malloc( ) when trying to allocate zero bytes is undefined.

Anonymous said...

For Third One:
If delete is used instead of delete[], then memory leak will happen. It won't give run-time error.

Vikram said...

Thank god, I took up MBA over technical job [:P]

uma said...

@sridhar,

I may have to digg into the compiler documentation to know the inner details of the implementation. Thanks for the info!.

uma said...

Another doubt with malloc():
Since the malloc() prototype is:
void* malloc(unsigned size_t),
if i pass -ve value as an argument, then it should be converted into +ve (automatically),
But i think its checking for the value passed, whether it is +ve/-ve, and when i pass -ve value, its raising segfault.

can u explain me why its so happenning?

uma said...

@Vikram,
Nice to see u back buddy, Howz ur preparation for majors?

Anonymous said...

Hi,

I agree with Sridhar.His explanation is logical. Coming to your question of -ve size, at the time of assignment (to the unsigned size_t) itself, the -ve should be changed to a +ve number isn't it. So it can't check for the value inside the malloc() method. If there is any checking it has to be done before assignment, which is unlikely. I don't know about that SegFault thing. The first thought is that either it should run or it should throw an out of memory kind of thing.

uma said...

@raghava,
u r right. it shdn't check intensionally. Data type values will be adjusted back if they are out of region.
But, if i tried:

int *p=malloc(sizeof(int)*-3);
if(p==NULL)
printf("Mem not allocated");
else
printf("Mem allocated");

what do u expect?
The output is: "Mem not allocated". may be it is try to locate large chunk of free contiguous memory and failing.

Its giving segfault coz im trying to access that pointer, for which memory wasnt created.

It means that malloc is failing to allocate that much memory.

i hav a reason, and not sure whether it is correct or not.
[for unsigned int, -1 equals to 65535, so compiler may be failing to find 65535 bytes of contiguous memory.]

I will check it tonight and let u know the result.

uma said...

Yup, I guessed it right. if i pass -1 as argument to malloc(), its converting into 4294967295, and malloc is failing to find that much large chunk of memory. So its not allocating any memory for the (-ve) case.

Anonymous said...

o.k. Guess that settles the issue. Had there been some exception throwing mechanism then it would have thrown that "Out of Memory" exception. What about C++,it has exception handling mechanism isn't.Does it throw any exceptions?

uma said...

@raghava,
I think exception handling in C++ is not as implicit as in Java. It wont generate exceptions until they were caugt. I am not sure about it. Lemme try!

uma said...

Got a link to amend Sridhar's comments:
a link from c faqs.

Anonymous said...

malloc.c implementation

http://felinemenace.org/~mercy/public/glibc-2.3.5/malloc/malloc.c

Check in description for public routines.

Anonymous said...

In the above source code, it says:

"Debugging:

Because freed chunks may be overwritten with bookkeeping fields, this malloc will often die when freed memory is overwritten by user programs. This can be very effective (albeit in an annoying way) in helping track down dangling pointers."

So segfaults caused in the malloc routine are usually due to (undetected) writing in non-allocated mem.

efence (compiled into any c code via "-lefence" compiler option) used together with gdb (dont forget "-g" option as well) shows where this happens.

Anonymous said...

sridhar said...

For the 4th one:
After freeing the dynamic memory, the contents at these adress are UNDEFINED. So it can have be anything.

Friday, November 24, 2006 1:14:00 PM
Uma said...

@sridhar,
UNDEFINED means, will the contents at that address intentionally change? Why compiler take time to change the contents. though, if changing then it shd put NULL, so that there won't be any 'garbage' concept.

Friday, November 24, 2006 2:19:00 PM
sridhar said...

The contents at that address might change or might not change. That memory might be allocated and might get changed.
You should not take into consideration how the compiler behaves. You have to consider the language documentation. Each compiler may implement it in different fashion. If you follow according to some compiler then your programs are not portable.

For First One:
The behaviour for malloc( ) when trying to allocate zero bytes is undefined.

Friday, November 24, 2006 7:31:00 PM
sridhar said...

For Third One:
If delete is used instead of delete[], then memory leak will happen. It won't give run-time error.

Friday, November 24, 2006 8:15:00 PM
Vikram said...

Thank god, I took up MBA over technical job [:P]

Saturday, November 25, 2006 1:57:00 AM
Uma said...

@sridhar,

I may have to digg into the compiler documentation to know the inner details of the implementation. Thanks for the info!.

Sunday, November 26, 2006 1:39:00 PM
Uma said...

Another doubt with malloc():
Since the malloc() prototype is:
void* malloc(unsigned size_t),
if i pass -ve value as an argument, then it should be converted into +ve (automatically),
But i think its checking for the value passed, whether it is +ve/-ve, and when i pass -ve value, its raising segfault.

can u explain me why its so happenning?

Sunday, November 26, 2006 1:45:00 PM
Uma said...

@Vikram,
Nice to see u back buddy, Howz ur preparation for majors?

Sunday, November 26, 2006 1:55:00 PM
Raghava said...

Hi,

I agree with Sridhar.His explanation is logical. Coming to your question of -ve size, at the time of assignment (to the unsigned size_t) itself, the -ve should be changed to a +ve number isn't it. So it can't check for the value inside the malloc() method. If there is any checking it has to be done before assignment, which is unlikely. I don't know about that SegFault thing. The first thought is that either it should run or it should throw an out of memory kind of thing.

Monday, November 27, 2006 2:28:00 PM
Uma said...

@raghava,
u r right. it shdn't check intensionally. Data type values will be adjusted back if they are out of region.
But, if i tried:

int *p=malloc(sizeof(int)*-3);
if(p==NULL)
printf("Mem not allocated");
else
printf("Mem allocated");

what do u expect?
The output is: "Mem not allocated". may be it is try to locate large chunk of free contiguous memory and failing.

Its giving segfault coz im trying to access that pointer, for which memory wasnt created.

It means that malloc is failing to allocate that much memory.

i hav a reason, and not sure whether it is correct or not.
[for unsigned int, -1 equals to 65535, so compiler may be failing to find 65535 bytes of contiguous memory.]

I will check it tonight and let u know the result.

Monday, November 27, 2006 3:13:00 PM
Uma said...

Yup, I guessed it right. if i pass -1 as argument to malloc(), its converting into 4294967295, and malloc is failing to find that much large chunk of memory. So its not allocating any memory for the (-ve) case.

Tuesday, November 28, 2006 9:57:00 AM
Raghava said...

o.k. Guess that settles the issue. Had there been some exception throwing mechanism then it would have thrown that "Out of Memory" exception. What about C++,it has exception handling mechanism isn't.Does it throw any exceptions?

Tuesday, November 28, 2006 10:42:00 AM
Uma said...

@raghava,
I think exception handling in C++ is not as implicit as in Java. It wont generate exceptions until they were caugt. I am not sure about it. Lemme try!

Tuesday, November 28, 2006 12:36:00 PM
Uma said...

Got a link to amend Sridhar's comments:
a link from c faqs.

Tuesday, November 28, 2006 3:45:00 PM
Anonymous said...

malloc.c implementation

http://felinemenace.org/~mercy/public/glibc-2.3.5/malloc/malloc.c

Check in description for public routines.

Thursday, January 04, 2007 4:07:00 PM
Anonymous said...

In the above source code, it says:

"Debugging:

Because freed chunks may be overwritten with bookkeeping fields, this malloc will often die when freed memory is overwritten by user programs. This can be very effective (albeit in an annoying way) in helping track down dangling pointers."

So segfaults caused in the malloc routine are usually due to (undetected) writing in non-allocated mem.

efence (compiled into any c code via "-lefence" compiler option) used together with gdb (dont forget "-g" option as well) shows where this happens.

Friday, April 06, 2007 4:54:00 PM

Anonymous said...

oops.

Anonymous said...

how do i format ur blog?

Post a Comment

Drop your message here to get in touch with me