I'm quite new to C so please bear with my incompetence. I want to read an whole EXEcutable file into a buffer:
#include <stdlib.h>
FILE *file = fopen(argv[1], "rb");
long lSize;
fseek(file, 0, SEEK_END);
lSize = ftell(file);
fseek(file, 0, SEEK_SET);
char *buffer = (char*) malloc(sizeof(char)*lSize);
fread(buffer, 1, lSize, file);
The file has 6144 bytes (stored correctly in lSize) but the size of my buffer is only 4 bytes, therefore only the MZ signature is stored in the buffer.
Why does malloc only allocate 4 bytes in this case?
Edit:
Probably the char buffer is terminated by the first 0 in the MZ header of the PE file. If I set the buffer to a certain value however, the whole file will be stored. If I set the buffer to int (= 4 bytes), the buffer won't be terminated but will be of course larger (vs. char = 1 byte). I just want to copy the file byte for byte with the null bytes as well.
Edit 2:
The buffer of course contains everything it should but if I try to write it to a new file with fwrite, it only wrote up to the first \0 (which is 4 bytes). I just got fwrite wrong. Fixed this. Sorry, the problem wasn't well defined enough.
If lSize really does equal 6144 then your code will indeed allocate 6144 bytes and then read the entire contents of the file. If you believe that only 4 bytes are being read it is probably because the 5th byte is a zero. Thus when buffer is interpreted as a zero terminated string, it terminates at that point.
You can inspect the rest of your buffer by looking at buffer[4], buffer[5], etc.
As an aside, you don't need to cast the return from malloc, and sizeof(char) == 1 by definition. Best practice is to write the malloc like this:
char *buffer = malloc(lSize);
But that will not change your results.
Why does malloc only allocate 4 bytes in this case?
Because you failed to #include <stdlib.h> (and cast the return value of malloc()).
Do not forget to #include <stdlib.h> so that the compiler knows malloc returns a value of type void* (rather than assuming it returns an int) and takes an argument of size_t type (rather than asuuming it is an int)
Also do not cast the return value of malloc. A value of type void* can be assigned to an object of pointer (to any type) type. Casting the return value makes the compiler silently convert int (assumed when <stdlib.h> was not included) to the type in the cast. Note the compiler would complain without the cast letting you know you had forgotten the include.
The real error is not malloc allocating the wrong amount (I believe it will allocate the correct amount anyway). The real error is assuming malloc returns an int when it returns a void*. int and void* can be passed differently (one in a register, the other on the stack for instance) or they have different representations (two's complement for int and segmented address for void*) or any other thing (most probably sizeof (int) != sizeof (void*)).
how are you checking for the size of buffer, are you doing a sizeof(buffer)? In that case you are only seeing the size of a pointer to int which is 4 bytes. You cannot get the size of a buffer out of it's pointer. You must store it separately as you have done (in lSize).
If malloc() did not return NULL then your buffer is fine and the size is correct.
Related
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.
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.
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.
What form is correct in allocating string in C?
char *sample;
sample = malloc ( length * sizeof(char) );
or
sample = malloc ( length * sizeof(char*) );
Why does char* take 4 bytes when char takes 1 byte?
Assuming the goal is to store a string of length characters, the correct allocation is:
sample = malloc(length + 1);
Notes:
Don't use sizeof (char), since it's always 1 it doesn't add any value.
Remember the terminator, I assumed (based on name) that length is the length in visible characters of the string, i.e. the return of strlen() will be length.
I know you didn't, but it's worth pointing out that there should be no cast of the return value from malloc(), either.
The reason char * is larger is that it's a pointer type, and pointers are almost always larger than a single character. On many systems (such as yours, it seems) they are 32 bit, while characters are just 8 bits. The larger size is needed since the pointer needs to be able to represent any address in the machine's memory. On 64-bit computers, pointers are often 64 bits, i.e. 8 characters.
Why does char* take 4 bytes when char takes 1 byte?
Because you are on a 32-bit systems, meaning that pointers take four bytes; char* is a pointer.
char always takes exactly one byte, so you do not need to multiply by sizeof(char):
sample = malloc (length);
I am assuming that length is already padded for null termination.
sample = malloc ( length * sizeof(char) );
First is the correct one if you want to allocate memory for length number of characters.
char* is of type pointer which happens to be 4 bytes on your platform. So sizeof(char*) returns 4.
But sizeof(char) is always 1 and smae is guaranteed by the C standard.
In the given cases you are doing two different things:
In the first case : sample = malloc ( length * sizeof(char) );
You are allocating length multiplied by the size of type char which is 1 byte
While in the second case : sample = malloc ( length * sizeof(char*) );
You are allocating length multiplied by the size of pointer to char which is 4 byte
on your machine.
Consider that while case 1 remains immutable, on the second case the size is variable.
sample = malloc(length);
is the right one
char* is a pointer, a pointer uses 4 bytes (say on a 32-bit platform)
char is a char, a char uses 1 byte
In your case, you want to alloc an array of length characters. You will store in sample a pointer to an array of length times the size of what you point to. The sizeof(char*) is the size of a pointer to char. Not the size of a char.
A good practice is
sample = malloc(length * sizeof(*sample));
Using that, you will reserve length time the size of what you want to point to. This gives you the ability to change the data type anytime, simply declaring sample to be another kind of data.
int *sample;
sample = malloc(length * sizeof(*sample)); // length * 4
char *sample;
sample = malloc(length * sizeof(*sample)); // length * 1
Provided the length already accounts for the nul terminator, I would write either:
sample = malloc(length);
or:
sample = malloc(length * sizeof(*sample));
sizeof(char*) is the size of the pointer, and it is completely irrelevant to the the size that the allocated buffer needs to be. So definitely don't use that.
My first snippet is IMO good enough for string-manipulation code. C programmers know that memory and string lengths in C are both measured in multiples of sizeof(char). There's no real need to put a conversion factor in there that everybody knows is always 1.
My second snippet is the One True Way to write allocations in general. So if you want all your allocations to look consistent, then string allocations should use it too. I can think of two possible reasons to make all your allocations look consistent (both fairly weak IMO, but not actually wrong):
some people will find it easier to read them that way, only one visual pattern to recognise.
you might want to use the code in future as the basis for code that handles wide strings, and a consistent form would remind you to get the allocation right when the length is no longer measured in bytes but in wide chars. Using sizeof(*sample) as the consistent form means you don't need to change that line of code at all, assuming that you update the type of sample at the same time as the units in which length is measured.
Other options include:
sample = calloc(length, 1);
sample = calloc(length, sizeof(char));
sample = calloc(length, sizeof(*sample));
They're probably fairly pointless here, but as well as the trifling secondary effect of zeroing the memory, calloc has an interesting difference from malloc that it explicitly separates the number and size of objects that you're planning to use, whereas malloc just wants the total size.
For any type T, the usual form is
T *p = malloc(N * sizeof *p);
or
T *p;
...
p = malloc(N * sizeof *p);
where N is the number of elements of type T you wish to allocate. The expression *p has type T, so sizeof *p is equivalent to sizeof (T).
Note that sizeof is an operator like & or *, not a library function; parentheses are only necessary if the operand is a type name like int or char *.
Please visit this Linkhttps://www.codesdope.com/c-dynamic-memory/for understand how it allocat the memory dynamically at run time. It might be helpful to understand the concept of malloc and how it allocate the amount of memory to the variable.
In your example;
char *sample;
sample = malloc ( length * sizeof(char) );
here, you are declare a pointer to character for sample without declaring how much memory it required. In the next line, length * sizeof(char) bytes memory is assigned for the address of sample and (char*) is to typecast the pointer returned by the malloc to character.
I am refreshing my C skills. I am using a char *s and using malloc to allocate memory to the s. Then using scanf, I read the input to s. But my question is I haven't specified a size for the memory chunk. But the program works. How does the memory gets allocated for the arbitrary length of the input string? Is scanf simply incrementing the pointer and writing data into the location?
#include <stdio.h>
#include <stdlib.h>
int main() {
char *s;
s = (char *) malloc(sizeof(s)); //I did not specify how much like malloc(sizeof(s) * 128)
if (s == NULL) {
fprintf(stderr, "\nError allocating memory for string");
exit(1);
}
scanf("%s", s);
puts(s);
free(s);
return 0;
}
/*
Input:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Output:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
*/
With char *s;, sizeof(s) is the same as sizeof(char *) which is either 4 or 8 depending on whether you are on a 32 bit box or a 64 bit box.
IF you are on a 32 bit box then you can store 3 characters plus the null 'end of string' character. IF you store more it may explode.
sizeof(s) returns the size in bytes of s which is of type char*. Typically on a 32 but machine this is 4 bytes and 8 byts on a 64 bit machine. So you actually have told malloc the number of bytes to allocate and s will point to that region of memory.
You did specify a size: sizeof(s). Since s is a char *, sizeof(s) == sizeof(char *). Depending on your platform, this may be 4 or 8 bytes in length.
So, you've effectively allocated 4 (or 8) bytes to store a string. If you type more than 3 (or 7) characters on the command line, then you are going to start writing past the end of the allocated array, which triggers undefined behaviour. With undefined behaviour, anything could happen: your program might look like it works fine, the program might fill the rest of the memory with ZALGO, the program might segfault horribly, or you might encounter the ever-popular nasal demons. The C specification does not specify what happens (hence the term "undefined behaviour").
The fact that your program "works" at all is a complete fluke, and should never be relied upon.
sizeof(s) is you case returns the size of a character pointer, which will be 4 or 8 bytes depending on if you are running on a 32 or 64 bit platform.
You want to use sizeof(*s) instead. However, since the C standard specifies that sizeof(char) (which is what sizeof(*s) will be) is one, so for character arrays you don't need it.
it will only allocate the space =size of char * and than
simply incrementing the pointer and writing data into the location? as you thought.
the answer for why it works is: because its writing it on the memory area which is not allocated to you but if the area is reserved by some other process your program will crash. so better allocate a larger space.
You are only allocating memory of size equal to size of Integer. If you write strings of greater length to this variable, it will just overwrite the existing memory locations and well, your program will show unexpected behavior.