malloc function in c? - c

I can't understand the reason of the output pf the following program
#include <stdio.h>
#include <stdlib.h>
int main(){
int* ip = (int*)malloc(100*sizeof(int));
if (ip){
int i;
for (i=0; i < 100; i++)
ip[i] = i*i;
}
free(ip);
int* ip2 = (int*)malloc(10*sizeof(int));
printf("%d\n", ip[5]);
printf("%d\n", ip2[5]);
ip[5] = 10;
printf("%d\n", ip2[5]);
return 0;
}
the output shows that ip & ip2 will have the same reference in the heap.
when we allocate a 100 int in(ip2) how did it return the same reference for ip1.
is it a feature of malloc function?
I know that malloc work like "new",right?
if it does then it should return some random reference,right?

All your outputs are undefined behavior, so they're not indicative of anything:
printf("%d\n", ip[5]); // ip was freed, so the memory it points to may not be accessed
printf("%d\n", ip2[5]); // reading uninitialized memory
ip[5] = 10; // writing to freed memory
printf("%d\n", ip2[5]); // still reading uninitialized memory
Generally, it's entirely possible that ip2 gets the same address that ip had. But you're not testing that in your code. You could do that like this, for instance:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* ip = (int*)malloc(100 * sizeof(int));
printf("%p\n", ip);
free(ip);
int* ip2 = (int*)malloc(100 * sizeof(int));
printf("%p\n", ip2);
free(ip2);
}
When I run that, I do actually get the same address twice (but there's no guarantee that this happens).

I don't really see what your problem is.
It is completely up to the library where it allocates the memory which is returned to you. Especially, it may or may not use the most recently freed memory block, as long as it is still free.
Your first malloc() reserves some memory, you write to it and then you free it.
Your second malloc() reserves some memory, you read from it then you free it.
What you read in the second step is completely arbitrary and only by coincidence the same as wou wrote to it in the first step.
You code also shows undefined behaviour, because you are not allowed to access ip[5] after the free(it).

This is a undefined behaviour which you shouldn't rely on. When you allocate a memory typically from a page memory, when you free it isn't freed to OS immediately and when try allocating again most likely you get the same which is hot in the cache. Typical OS memory unit allocates the same size in next iteration from same memory freed blocks in LIFO fashion.

Related

Strange memory allocation in case of pointers using malloc

#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a = (int *)malloc(sizeof(int));
// int a[1];
int i;
for(i = 0; i < 876; ++i)
a[i] = i;
printf("%d",a[799]);
}
Why is this code working, even if, I am allocating only 1 int's space using malloc()?
Why is this code working? Even if, I am allocating only 1 int's space using malloc ? In such case answer in undefined behavior.
Allocating block of 4 bytes like
int *a = (int *)malloc(sizeof(int)); /* No need to cast the malloc result */
and accessing beyond that like
a[i] = i; /* upto i<1 behavior is guaranteed as only 4byte allocated, not after */
results in undefined behavior i.e anything can happen and you shouldn't depend on it doing the same thing twice.
Side note, type casting the result of malloc() is not required as malloc() return type void* & its automatically promoted safely into required type. Read Do I cast the result of malloc?
And always check the return value malloc(). for e.g
int *a = malloc(sizeof(int));
if( a != NULL) {
/* allocated successfully & do_something()_with_malloced_memory() */
}
else {
/* error handling.. malloc failed */
}
It seems to be working. There is absolutely zero guarantee it will work the same way after a recompile, or in a different environment.
Basically, here you're trying to access memory address, which is not allocated to your program (using any index other than 0). So, from your program point of view, the memory address is invalid. Accessing invalid memory location invokes undefined behaviour.
As others have explained, the behavior while accessing a memory region beyond what is allocated, is undefined. Run the same program on a system which is running memory intensive applications. You might see a SIGSEGV. Run your code through coverity static analysis and you will see it catching the buffer overrun.

Is malloc needed for this int pointer example?

The following application works with both the commented out malloced int and when just using an int pointer to point to the local int 'a.' My question is if this is safe to do without malloc because I would think that int 'a' goes out of scope when function 'doit' returns, leaving int *p pointing at nothing. Is the program not seg faulting due to its simplicity or is this perfectly ok?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct ht {
void *data;
} ht_t;
ht_t * the_t;
void doit(int v)
{
int a = v;
//int *p = (int *) malloc (sizeof(int));
//*p = a;
int *p = &a;
the_t->data = (void *)p;
}
int main (int argc, char *argv[])
{
the_t = (ht_t *) malloc (sizeof(ht_t));
doit(8);
printf("%d\n", *(int*)the_t->data);
doit(4);
printf("%d\n", *(int*)the_t->data);
}
Yes, dereferencing a pointer to a local stack variable after the function is no longer in scope is undefined behavior. You just happen to be unlucky enough that the memory hasn't been overwritten, released back to the OS or turned into a function pointer to a demons-in-nose factory before you try to access it again.
Not every UB (undefined behaviour) results in a segfault.
Normally, the stack's memory won't be released back to the OS (but it might!) so that accessing that memory works. But at the next (bigger) function call, the memory where the pointer points to might be overwritten, so your data you felt like bing safe there is lost.
malloc() inside a function call will work because it stores on heap.
The pointer remains until you free the memory.
And yes, not every undefined behaviour will result in segmentation fault.
It does not matter that p does not point at anything on return from doit.
Because, you know, p isn't there any more either.
It does matter that you are reading the pointer to a no-longer-existing object in main though. That's UB, but harmless on most modern platforms.
Even worse though, you are reading the non-existent object it once pointed to, which is straight Undefined Behavior.
Still, nobody is obliged to catch you:
Can a local variable's memory be accessed outside its scope?
As an aside, Don't cast the result of malloc (and friends).
Also, be aware that not free-ing memory is not harmless on all platforms: Can I avoid releasing allocated memory in C with modern OSes?
Yes, the malloc is needed, otherwise the pointer would point on the 4-byte space of the stack, which would be used by other data, if you called other functions or created now local variables.
You can see that if you call that function afterwards with a value of 10:
void use_memory(int i)
{
int f[128]={};
if(i>0)
{
use_memory(i-1);
}
}

How much memory does calloc actually allocate?

The following code when tested, gives output as
1
0
0
2
0
which is amazing because ptr[3], ptr[4] did not have any memory allocation. Although they stored value in them and prints it. I tried the same code for few larger i's in ptr[i] which again compiled successfully and gives result but for very large value of i, of the order of 100000,program get crashed. if calloc() allocates such a large memory on single call then it is not worth effective. So how calloc() works? Where is this discrepancy?
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));//allocates memory to 3 integer
int i = 0;
*ptr = 1;
*(ptr+3) = 2;//although memory is not allocated but get initialized
for( i =0 ; i<5 ; ++i){
printf("%d\n",*ptr++);
}
}
After that i tried this code which continuously runs without any output
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));
int i = 0;
*ptr = 1;
*(ptr+3) = 2;
//free(ptr+2);
for( ; ptr!=NULL ;)
{
//printf("%d\n",*ptr++);
i++;
}
printf("%d",i);
}
You are confounding two kinds of memory allocation: the kernel's and libc's.
When you ask malloc or calloc for 5 bytes, it does not turn around and ask the kernel for 5 bytes. That would take forever. Instead, the libc heap system obtains larger blocks of memory from the kernel, and subdivides it.
Therefore, when you ask for a small amount of memory, there is usually plenty of more accessible memory right after it that has not been allocated yet by libc, and you can access it. Of course, accessing it is an instant recipe for bugs.
The only time that referencing off the end will get a SIGnal is if you happen to be at the very end of the region acquired from the kernel.
I recommend that you try running your test case under valgrind for additional insight.
The code that you have has undefined behavior. However, you do not get a crash because malloc and calloc indeed often allocate more memory than you ask.
One way to tell how much memory you've got is to call realloc with increasing size, until the pointer that you get back is different from the original. Although the standard does not guarantee that this trick is going to work, very often it would produce a good result.
Here is how you can run this experiment:
int *ptr = calloc(1,sizeof(int));
// Prevent expansion of the original block
int *block = calloc(1, sizeof(int));
int *tmp;
int k = 1;
do {
tmp = realloc(ptr, k*sizeof(int));
k++;
} while (tmp == ptr);
printf("%d\n", k-1);
This prints 4 on my system and on ideone (demo on ideone). This means that when I requested 4 bytes (i.e. one sizeof(int) from calloc, I got enough space for 16 bytes (i.e. 4*sizeof(int)). This does not mean that I can freely write up to fourints after requesting memory for a singleint`, though: writing past the boundary of the requested memory is still undefined behavior.
calloc is allocating memory for 3 int's in the given snippet. Actually you are accessing unallocated memory. Accessing unallocated memory invokes undefined behavior.
calloc allocates only the amount of memory that you asked, which in your case in for 3 int variables
but it doesnt create a bound on the pointer that it has created (in your case ptr). so you can access the unallocated memory just by incrementing the pointer. thats exactly whats happening in your case..

Allocating and initialising a pointer in C

So, I am new to pointers to in C.
I am facing a confusion.
If I have,
int a;
Here, I dont allocate memory manually for a. It's done automatically by the compiler.
Now, if in a similar fashion, if I do,
char * a;
Do I need to allocate memory for the pointer?
Secondly, I made this code,
#include <stdio.h>
int main (void)
{
int *s=NULL;
*s=100;
printf("%d\n",*s);
return 0;
}
Why do I get a seg fault in this code? Is it because I havent allocated memory for the pointer? But as asked in the above question, I can simply declare it as well without manually allocating the memory.
PS: I am new to pointers and I am facing confusion in this. Spare me if it is a bad question. Thanks.
Edit: I read the post for malloc on SO.
http://stackoverflow.com/questions/1963780/when-should-i-use-malloc-in-c-and-when-dont-i
It doesnt really solve my doubt.
You don't need to allocate memory for the pointer itself. That's automatic, like the int in your first code snippet.
What you do need to allocate is the memory that the pointer should point to, and you need to initialize the pointer to point to that.
Since you're not allocating any space, the *s= assignment is undefined behavior. s itself (the pointer) is allocated, and initialized to NULL. You can't dereference (*s - look at what the pointer points to) a null pointer.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int *s = NULL; // s is created as a null pointer, doesn't point to any memory
s = malloc(sizeof(int)); // allocate one int's worth of memory
*s = 100; // store the int value 100 in that allocated memory
printf("%d\n",*s); // read the memory back
free(s); // release the memory
// (you can't dereference s after this without
// making it point to valid memory first)
return 0;
}
You have to allocate memory for the variable s you are declaring. Malloc is a nice way to do that. With int *s=NULL the pointer does not point to any address. And after that you trying to give a value to that address (*s=100;). If you do not want to allocate memory manualy (with malloc) you simply declare an int variable and then make s pointing to that variable.
With malloc:
#include <stdio.h> int main (void)
{
int *s=NULL;
s=(int *)malloc(sizeof(int));
*s=100;
printf("%d\n",*s);
return 0;
}
Without malloc:
#include <stdio.h>
int main (void)
{
int *s=NULL;
int var;
s=&var;
*s=100;
printf("%d\n",*s);//100
printf("%d\n",var);//also 100
return 0;
}
As pointers are also special type of variables which stores the address of other variables,As the address is also some value(number), Hence memory is also needed to store this address,so compiler automatically allocates memory(exactly 4 bytes on 32-bit machine) to a pointer variable,when you are allocating the memory using malloc() or calloc()your are actually allocating the memory to the data which is to be stored,and simply assigning the starting address of this memory to the pointer.
In your example at the line
int *s=NULL; //this line
Compiler actually allocates memory of 4 bytes (if your machine is 32-bit)
see this small snippet
int main(void)
{
int *s=NULL;
printf("%d\n",sizeof(s)); //Will output 4 if you are using is 32-bit OS or else 2 if you are using using 16 bit OS.
return 0;
}
And NULL is simply just another way of assigning Zero to a pointer.So technically your actually using 4 bytes to store zeros in that pointer. And don't be confused, assigning zero or NULL means that the pointer is not pointing to any data(as it doesn't hold a valid address,Zero is not valid address).

Does "ptr=malloc(sizeof(char)*10)" use many times,one after another allocate pointer to same memory block or cause memory leak?

Suppose I have the following piece of code in my program:
char *ptr;
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
Will a pointer to the same memory block be assigned to ptr each time,or a separate piece of memory be reserved each time and its pointer assigned to ptr,resulting in memory leak each time malloc() is called?
I am still learning C so bear with me if it's too basic.I tried googling but found no answer.
EDIT::
Thanks for your answers.Please tell me if this approach of me deals with the memory leak risk.My program simply asks for names of 5 people and displays it,without using static arrays.After reading your answers,I put the free(ptr) inside the loop,else before I had planned to use it only once outside the loop,after the loop.Am I correct now?
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
int main ()
{
char *names[5],*ptr;
int i;
for(i=0;i<=4;i++)
{
ptr=malloc(sizeof(char)*10);
printf("Enter name no.%d : \n",i+1);
scanf("%s",ptr);
names[i]=malloc(strlen(ptr)+1);
strcpy(names[i],ptr);
free(ptr);
}
for(i=0;i<=4;i++)
printf("%s\n",names[i]);
}
malloc() will never return the same memory block multiple times, unless (of course) it has been free()'d since the last time it was returned. This is guaranteed by the C standard. Therefore, your code also leaks memory. Any memory allocator that handed out the same piece of memory twice would be worse than useless: Applications would step on their own toes, using the same piece of memory for different purposes, likely concurrently.
Edit: Barring buffer overflow issues, your code is correct in that it frees the 10-char buffers referenced via ptr. Calling free(ptr) just once, outside the loop, would indeed be incorrect. However, your code (as shown here) does not free the memory allocated later in the loop body stored in names[i].
A separate block of memory will be allocated each time, since C does not perform any garbage collection and no free calls are done in between the malloc calls. The first three blocks are leaked since you're not keeping pointers to them.
You can find out for yourself that the pointers are all distinct using a simple printf call:
for (int i = 0; i < 4; i++) {
ptr = malloc(10); // no need for sizeof(char), it's 1 by definition
printf("%p\n", ptr);
}
This should print four distinct numbers.
This will cause a memory leak assuming each call is successful, all but the memory allocated to the last malloc will be inaccessible. You either need to keep a pointer to each block allocated by malloc or you need to free between successive calls. so yes, malloc will attempt to allocate distinct block of memory for each call. A quick test could be as follows:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr;
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
}
This will print out the address allocated each time. If you added a free between each call to malloc you may end up with the same pointer, a quick test demonstrated this behavior.
Yes, each malloc call will allocate a new block, which means that the previous one will be leaked.
EDIT: answer to the edited part of the question
You are now correctly releasing the blocks to which ptr points, however you are not releasing those allocated for names. You would also need:
for(i=0;i<=4;i++) {
printf("%s\n",names[i]);
free(names[i]);
}
In your case, you could skip using ptr and work on names directly. Here's an equally [un]safe version:
char *names[5];
int i;
for(i=0; i < 5; i++)
{
names[i] = malloc(10);
printf("Enter name no.%d : \n",i+1);
scanf("%s",names[i]); // what if name is longer than 10 characters?
}
for(i=0; i < 5; i++)
{
printf("%s\n",names[i]);
free(names[i]);
}
However, operating system will reclaim the memory consumed by a process once the process exits, so in this simple example you don't have to worry, but I guess that this is only an illustration. I also assume that you don't care about user entering names longer than 10 characters which would write over the boundaries of allocated buffers.
Your second part is right: it's a memory leak.
A new block of memory is allocated each time you call malloc. This will create a memory leak as you have no way to reference the first three allocations to free them.
You can check memory leaks by using valgrind,its very useful in detecting memory leaks.
valgrind ./progr

Resources