How does the malloc function work in C? - c

My goal is to read a file and store it's contents in a char array given the offset and number of bytes to be read. I have written a function for doing the same and it works fine.
Now this function is to be called from somewhere else. So I am trying to declare a variable char * data which will hold the contents returned by the above mentioned function. After declaring I tried to allocate it some memory. (I know how much, as I specify the number of bytes to be read). It goes as follows:
char * data;
char * filename = "alphabet.txt";
int data_size = 10;
printf("data size: %d\n", data_size);
data = (char*) malloc (data_size);
printf("Size allocated to data: %d\n",sizeof(data));
return 0;
This code gives the following output:
data size: 10
Size allocated to data: 8
I don't understand this behavior. Can somebody please explain it to me.
Thanks a lot
shahensha

This has nothing to do with malloc.
sizeof does its thing at compile time, not runtime. sizeof(data) is the same as sizeof(char*). Your program cannot know at compile time how much memory that pointer refers to.
On the other hand, sizeof(some_array) would work as you expect because array sizes are known at compile time.

sizeof char *ptr will give the sizeof the pointer address ptr pointing . Its vary depends on the machine.
char *ptr = malloc(10); malloc will allocate the 10 space and ptr pointing
to the starting address.
Examine below code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char * data;
int data_size = 10;
printf("data size: %d\n", data_size);
data = malloc ((data_size+1)*sizeof(char));
strcpy(data, "datadatada");
printf("string lenght: %d\n",strlen(data));
printf("Size allocated to data: %zd\n",sizeof(data));
return 0;
}

Just these two lines of code
char * data;
printf("Size allocated to data: %d\n",sizeof(data));
would print (in OP's machine):
Size allocated to data: 8
sizeof returns the size of the argument, here data pointer. It is done at compile time.
malloc has nothing to do with sizeof(data).

Apparently you made some completely unfounded assumptions about the behavior of sizeof. Apparently you assumed that sizeof can be used to query the size of malloc-ed memory block.
It can't be. sizeof has absolutely nothing to do with that. In fact, C library does not provide you with any means to determine the size of malloc-ed memory block. It is simply impossible. If you want to know how much memory you allocated, you have to devise your own way to remember how much memory you requested from malloc. End of a story.
sizeof evaluates to the size of its operand. In this case you supplied a pointer as its operand, so it evaluated to the size of a pointer, which happens to be 8 on your platform.

Related

inserting elements to a dynamically allocated array [duplicate]

I was getting realloc(): invalid next size for a program. So I just coded this to understand what's happening.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *inp;
printf("%lu ",sizeof(inp));
char *res = (char*)malloc(15*sizeof(char*));
printf("%lu ",sizeof(res));
res = "hello world";
printf("%lu\n",sizeof(res));
return 0;
}
And surprisingly it outputs 8 8 8. Can anyone explain why is it like that? Why is it 8 by default? And how malloc() effects size of inp?
sizeof(inp) gives you the size of pointer (8 bytes, 64-bits), not the storage under that pointer.
You are using sizeof.returns size in bytes of the object representation of type. Remember sizeof is an operator.
Now sizeof is returning here 8 a constant type of size_t
Why isn't it changing? because in all tha cases you are using the same type that is char *.
Here 8 bytes is the size of the character pointer that is 64 bit.
You can probably have a look at this-
printf("size of array of 10 int: %d\n" sizeof(int[10]));
This will give the output:40. 40 bytes.
And malloc will never affect the size of a char*. It still needs 64 bits to store an address of a dynamically allocated space from heap.
Is it possible to determine size of dynamically allocated memory in c?
There is no standard way to do this. You have to take this overhead on your own. You may find some extensions to the compiler that may accomplish this.
sizeof(inp) in your case is sizeof(pointer) and hence sizeof(char-pointer) on your system is 8 bytes which is a constant. While allocating memory using malloc() you would have specified the size so why do you need to get the size of the allocated space again?
And I see res is being initialized and not inp
****EDIT**** : The below post was written before the edit of the question.
You're missing stdlib.h, to the most, for function malloc() to work properly. After that,
Point 1:
char *res = (char*)malloc(15*sizeof(char*));
should be
char *res = malloc(15); //will also issue warning to resolve missing stdlib.h
Point no note: you should be allocating memory for chars, not char *s. Then , you should write sizeof(char), not sizeof(char *). Also, sizeof(char) is always 1 in C. So, can omit that part.
Please read: do not cast the return value of malloc() and family in C.
Point 2:
strings are not supposed to be assigned to already malloc()ed pointers. use strcpy() instead.
inp = "hello world";
should be
strcpy(inp, "hello world");
Otherwise, you'll overwrite the previously allocated memory, returned by malloc(). The assignment will overwrite the memory location held by inp, causing memory leak.
Point 3.
sizeof() operator returns a value of size_t. To print that, you need %zu format specifier.
Related, from C11 standard document, chapter §7.21.6.1, paragraph 7,
z
Specifies that a following d, i, o, u, x, or X conversion specifier applies to a
size_t or the corresponding signed integer type argument; or that a
following n conversion specifier applies to a pointer to a signed integer type
corresponding to size_t argument.
Then, to answer the query about the output, in all the cases, you're printing sizeof(inp) which is essentially sizeof(char *) and that value is fixed for a particular platform (8, in your case).
Just FYI, sizeof() is an operator, it's not a function. It returns the size of the datatype, not the amount of space pointed by the variable.

Should I change the pointer to an array?

for (int a=0; a<10; ++a) {
printf ("%d", a);
}
char *foo;
foo = (char*)malloc(a);
I want to store more than one char value in foo variable.
Should I change it to an array, since the buffer is only allocating 1 char length?
Is 1 the longest length that can be stored in this buffer?
Well, foo now points to some useable address of a bytes, because this is how malloc() works. It doesn't matter if its type is char *, void * or anything else, you can only use a bytes.
Here, you increment a to 10. That means you can store 10 bytes, being 10 chars, (because in the context of C, 1 char = 1 byte), starting at the address where foo points to. Using a pointer or an array is strictly equivalent.
Since the buffer is only allocating 1 char length...
No, it is not the case here.
Quoting from the C11 standard, chapter §7.22.3.4, The malloc function
void *malloc(size_t size);
The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
So, in case of
foo = malloc(a); //yes, the cast is not required
a memory of size same as the value of a will be allocated, considering malloc() is successful.
Simply put, if I write a snippet like
int * p = malloc(10 * sizeof*p);
then, I can also write
for (int i = 0; i < 10, i++)
p[i] = i;
because, I have allocated the required memory for 10 ints.
That said, please see this discussion on why not to cast the return value of malloc() and family in C..
There are a couple of things you could do in a case like this.
If you know at compile time how many chars you want to store you could make it an array char foo[10]; If you know that there is always going to be 10 (or less) characters you want to store.
If you are not sure how many chars it needs to hold at compile time you would typically do dynamic allocation of memory using malloc. Now when using malloc you specify how many bytes of memory you want so for 12 chars you would do malloc(12) or malloc(12 * sizeof(char)). When using malloc you need to manually free the memory when you are done using it so the benefit of being able to ask for arbitrary (within limits) sizes of memory comes at the cost of making memory management harder.
As a side note: You typically do not want to cast the return value of malloc since it can hide some types of bugs and void *, that malloc returns can be implicitly cast to any pointer type anyway.

Size of dynamic array in C doesn't change

I was getting realloc(): invalid next size for a program. So I just coded this to understand what's happening.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *inp;
printf("%lu ",sizeof(inp));
char *res = (char*)malloc(15*sizeof(char*));
printf("%lu ",sizeof(res));
res = "hello world";
printf("%lu\n",sizeof(res));
return 0;
}
And surprisingly it outputs 8 8 8. Can anyone explain why is it like that? Why is it 8 by default? And how malloc() effects size of inp?
sizeof(inp) gives you the size of pointer (8 bytes, 64-bits), not the storage under that pointer.
You are using sizeof.returns size in bytes of the object representation of type. Remember sizeof is an operator.
Now sizeof is returning here 8 a constant type of size_t
Why isn't it changing? because in all tha cases you are using the same type that is char *.
Here 8 bytes is the size of the character pointer that is 64 bit.
You can probably have a look at this-
printf("size of array of 10 int: %d\n" sizeof(int[10]));
This will give the output:40. 40 bytes.
And malloc will never affect the size of a char*. It still needs 64 bits to store an address of a dynamically allocated space from heap.
Is it possible to determine size of dynamically allocated memory in c?
There is no standard way to do this. You have to take this overhead on your own. You may find some extensions to the compiler that may accomplish this.
sizeof(inp) in your case is sizeof(pointer) and hence sizeof(char-pointer) on your system is 8 bytes which is a constant. While allocating memory using malloc() you would have specified the size so why do you need to get the size of the allocated space again?
And I see res is being initialized and not inp
****EDIT**** : The below post was written before the edit of the question.
You're missing stdlib.h, to the most, for function malloc() to work properly. After that,
Point 1:
char *res = (char*)malloc(15*sizeof(char*));
should be
char *res = malloc(15); //will also issue warning to resolve missing stdlib.h
Point no note: you should be allocating memory for chars, not char *s. Then , you should write sizeof(char), not sizeof(char *). Also, sizeof(char) is always 1 in C. So, can omit that part.
Please read: do not cast the return value of malloc() and family in C.
Point 2:
strings are not supposed to be assigned to already malloc()ed pointers. use strcpy() instead.
inp = "hello world";
should be
strcpy(inp, "hello world");
Otherwise, you'll overwrite the previously allocated memory, returned by malloc(). The assignment will overwrite the memory location held by inp, causing memory leak.
Point 3.
sizeof() operator returns a value of size_t. To print that, you need %zu format specifier.
Related, from C11 standard document, chapter §7.21.6.1, paragraph 7,
z
Specifies that a following d, i, o, u, x, or X conversion specifier applies to a
size_t or the corresponding signed integer type argument; or that a
following n conversion specifier applies to a pointer to a signed integer type
corresponding to size_t argument.
Then, to answer the query about the output, in all the cases, you're printing sizeof(inp) which is essentially sizeof(char *) and that value is fixed for a particular platform (8, in your case).
Just FYI, sizeof() is an operator, it's not a function. It returns the size of the datatype, not the amount of space pointed by the variable.

Realloc Function not Working correctly?

Why does the following code output 4 twice, instead of 8 and 20?
Thanks
int size = 0;
int *pointer;
pointer = malloc(2 * sizeof(int));
size = sizeof(pointer);
printf("%d", size);
int *temp = realloc(pointer, 5 * sizeof(int));
if (temp != NULL) //realloc was successful
{
pointer = temp;
} else //there was an error
{
free(pointer);
printf("Error allocating memory!\n");
}
size = sizeof(pointer);
printf("%d", size);
sizeof is a compile-time operator that tells you how much space a variable or a type takes up. The answer you get is a constant. In the case of a pointer, sizeof tells you how many bytes it takes to store a memory address. This is typically 4 bytes on a 32-bit platform and 8 bytes on a 64-bit one.
It does not tell you how much memory has been allocated by malloc(). As it turns out, there unfortunately is no standard function to tell you the size of an allocated memory block. You have to keep track of it yourself.
sizeof is evaluated at compile time, not run time (except in the case of variable length arrays, an odd feature of C99). In this case you're taking the size of the pointer, which is 4 bytes. Even if you took sizeof(*pointer), that would be equivalent to saying sizeof(int)
I realize you're trying to tell the size of the dynamically allocated memory, but there is no standard way to do this. You should just keep track of it yourself, in your own code.

How I return the size of the pointer that I have allocate with malloc?

See this example!
int main( int argc, char ** argv )
{
int *ptr = malloc(100 * sizeof (int));
printf("sizeof(array) is %d bytes\n", sizeof(ptr));
}
The printf function return only 4 bytes!
What is wrong?
Thanks so much!!!
Nothing is wrong. You are asking for, and getting, the size of the pointer on your platform.
It is not in general possible to get the size of the memory block that a pointer points at, you must remember it yourself if you need it later.
On some platforms there is the "msize" function that returns the size of an area allocated by malloc/calloc/strdup. But this is not standard.
You cannot print the size of the memory block you received. Either malloc allocates all the memory you requested or it does not (and returns NULL).
The sizeof() operator does what you request: it tells you the size of the pointer - and the pointer itself occupies 4 bytes in memory.
Nothing is wrong, that's the size of any pointer on a 32 bit platform.

Resources