Hello again, I am back with more stupid and outrageous questions. This time I am trying to understand how malloc really works. Experimenting a bit, I came to some conclusions, that I would like you, to either confirm them, or bludgeon the newbie out of me. Let's start with something very basic:
Code:
malloc(sizeof(int));
This statement should allocate 4 bytes in the heap for our program (provided that an int is 4 bytes long) and it is equivalent with the statement:
Code:
malloc(4); // bad practice I know but bear with me
Is the above conclusion right?
I am asking the confirmation to that because the following program compile and run fine when it shouldn't
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *cp;
cp = malloc(sizeof(int)); /* Using sizeof(int) is deliberate, although
bad practice. */
if (cp == NULL) {
printf("Error with malloc!");
exit(EXIT_FAILURE);
}
strcpy(cp, "abcdef"); /* Only abcd can fit into the allocated block
e, f, and \0 are out. */
printf("string: %s", cp);
free(cp);
cp = NULL;
return 0;
}
Output is string: abcdef. I am sure that I have 98% right (and not caring about the rest 3%) when I am saying that the above code, results in undefined behavior, since I write outside the block allocated by malloc. The only problem is that for every string I tried, I always got the correct output, and the program never crashed or produced inconsistencies. Can you please confirm me that the code above is undefined behavior and I am just being "lucky" ?
If I hadn't free the allocated memory, after the program was finished what would have happened to the block ?
Another set of questions after the following code
Code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
struct test {
int a;
int b;
};
struct test *sp;
sp = malloc(sizeof(*sp));
sp -> a = 10;
sp -> b = 20;
printf("a = %d, b = %d", (*sp).a, (*sp).b);
free(sp);
sp = NULL;
return 0;
}
Is malloc(sizeof(*sp)) the same as malloc(sizeof(struct test)) ?
If yes which one is best practice ?
Is it possible to have some pointer, of type int, pointing at the block we allocated with malloc above?
I did try to make it happen but I wasn't able. Can you please give me a hint, to produce the correct code, in case such practice is possible?
I believe that when we wrote sp = malloc(sizeof(*sp)); we didn't create any object of type "struct test" in the allocated block. We merely reserved 8 bytes for our program in the heap, and the fact that we can read and write in that block, as if it were a structure of type test, is due to the properties of the pointer that malloc returned.
If (in theory) could have a second pointer of type int pointing at the allocated block, we could manipulate the data in there. See my theoretic code below
Code:
.
.
struct test {
int a;
int b;
};
struct test *sp;
int *ip;
sp = malloc(sizeof(struct test));
ip = I don't know how but we make this pointer point at the same block;
*ip = 10;
*(ip + 1) = 20;
printf("a = %d, b = %d", sp -> a, sp -> b);
.
.
Is the above (theory) correct at some (any) level ?
Is it possible to directly acquire the size of the allocated memory in the heap, let's say through some hidden byte in the block that contains such info? Or the bytes of the block are exactly the number inside malloc(number) ?
If we move the pointer in the middle or the last byte of the allocated memory can we still free it with free(pointer_moved) ?
If we assign a secondary pointer at the allocated memory can we free the block through that pointer free(secondary_pointer) ?
I thank you very much for your time to read through this.