Allocating memory with calloc for an int pointer - c

Hey guys given the example below in C when operating on a 64bit system as i understand, a pointer is 8 byte. Wouldn't the calloc here allocate too little memory as it takes the sizeof(int) which is 4 bytes? Thing is, this still works. Does it overwrite the memory? Would love some clarity on this.
Bonus question: if i remove the type casting (int*) i sometimes get a warning "invalid conversion from 'void*' to 'int*', does this mean it still works considering the warning?
int *ptr;
ptr = (int*)calloc(4, sizeof(int));

calloc is allocating the amount of memory you asked for on the heap. The pointer is allocated by your compiler either in registers or on the stack. In this case, calloc is actually allocating enough memory for 4 ints on the heap (which on most systems is going to be 16 bytes, but for the arduino uno it would be 8 because the sizeof(int) is 2), then storing the pointer to that allocated memory in your register/stack location.
For the bonus question: Arduino uses C++ instead of C, and that means that it uses C++'s stronger type system. void * and int * are different types, so it's complaining. You should cast the return value of malloc when using C++.

Related

Getting a pointer to a memory address from a different pointer C

I'm writing my own memory allocater. I'm getting a pointer to mapped memory from mmap. From there, I want to be able to get a pointer to a different part of that mapped memory (like x bytes away from the current pointer). How can I do this? Memory management is very confusing to me.
mmap gives you a void* and C doesn't allow pointer arithmetic with those, but you can cast it to char* and then just add the number of bytes you want, e.g. mypointer + 16.
If you cast the pointer to a larger type (like int*), pointer arithmetic adds multiples of the size of that type. For example, if you add 16 to an int*, you're adding enough bytes for 16 int values (so 64 bytes, assuming sizeof(int) is 4).

Compatibility of data size while using malloc()

I recently studied about malloc() in C with declaration as follows:
void *malloc(size_t size)
where size_t is unsigned int and size defines the no. of bytes to be reserved.
Question is that on my system float values occupy 4bytes of memory. So if i make memory pointer(of float type) using malloc of 2bytes,
float *p;
p = (float *)malloc(2);
then how come it does not give any error? Because what i think is that float data required 4 bytes so if i issue only 2 bytes to it then it may lead to some data loss.
or is it that i m understanding malloc() incorrrectly?
In the example you give, if you only allocate 2 bytes for a float * and then attempt to write to that location by dereferencing the pointer, you'll be writing to memory that hasn't been allocated. This results in undefined behavior. That means it might work, it might core dump, or it might behave in unpredictable ways.
If you want to allocate memory for one or more floats, you would do it like this:
// allocates space for an array of 5 floats
// don't cast the result of malloc
int arrayLen = 5;
float *f = malloc(sizeof(float) * arrayLen);
You're encountering an implementation-specific result of the requirements of the C Standard:
7.22.3 Memory management functions
The order and contiguity of storage allocated by successive calls to
the aligned_alloc , calloc , malloc , and realloc functions
is unspecified. The pointer returned if the allocation succeeds is
suitably aligned so that it may be assigned to a pointer to any type
of object with a fundamental alignment requirement and then used to
access such an object or an array of such objects in the space
allocated (until the space is explicitly deallocated).
In order to provide storage "suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement", an implementation has to return memory from malloc() et al at specific offsets that are multiples of the most restrictive alignment requirement for the system. That's usually something like 8 or 16 bytes.
Given that each and every block returned has to be aligned that way, most implementations internally create blocks of memory in multiples of the alignment requirement.
So if your system has an 8-byte alignment requirement, your malloc() implementation is likely to actually give you an 8-byte block of memory even though you requested two bytes. Likewise, ask for 19 bytes and you'll likely get something like 24 in reality.
It's still undefined behavior to go beyond what you asked for, though. And undefined behavior does unfortunately include "works just fine".
This can be problematic if you try to use that pointer -actually the pointer is fine, it's the allocated memory it points to that's too small-, the reason the compiler doesn't recognize it as an error is the fact that the pointer isn't "aware" of what it points to , actually pointers are variables that contain memory addresses, so basically they're just a number, and in most cases ( as user694733 pointed out) the size of the pointer is the same whether it points to a short or a float.
what the compiler sees is a cast from (void*) to (float*) and to the compiler it's a totally valid cast.
Your question has actually nothing to do with the malloc, but rather to the data casting. In this case you have casted the bytes located starting from the address returned by malloc to float. Thus, if you later say *p = 0.0f; you will actually write 4 bytes to the mentioned memory area, but only 2 bytes are ligal to you to use since you have allocated only 2 bytes. Therefore, your code will compile and run with memory corruption (this either will result in crash, or in an unexpected runtime behavior later)

size of memory allocated by malloc

I am assigning a new memory chunk to a pointer, but apparently the size of the chunk is not the one which I pass as a parameter to malloc
char *q="tre";
printf("q in main %zu\n", sizeof(q));
q = (char*)malloc(6);
printf("q in main %zu\n", sizeof(q));
Outputs
8
8
The pointer however does point to a new memory chunk.
How is this possible?
sizeof returns size of pointer, in your case it is (char*), it will not give the memory allocated by the malloc. Keep the memory size in separate variable for later use.
char *q;
printf("%zu\n", sizeof(q));
sizeof(q) refers to the size of the pointer, not the amount of memory it points to.
What you are obtaining is the size of the variable q as a pointer type. In general all pointers will have the same size in your program.
Since 8 bytes are 64 bits, it seems you are doing 64-bit applications. :)
sizeof(q) returns the size of the pointer q which will on a 64 bit machine be 8 bytes, not the size of the memory block allocated at that pointer. sizeof is a compile time not a runtime operation.
I'm not clear what you want to do here, but if you want to allocate enough memory for a string at location s, then you want to malloc(strlen(s)+1) (+1 for the terminating NULL).
Perhaps you want to get the size of malloc()ed block. There is not a portable way to do this to my knowledge, but malloc_usable_size nearly does it on glibc. From the man page:
malloc_usable_size() returns the number of bytes available in the dynamically allocated buffer ptr, which may be greater than the requested size (but is guaranteed to be at least as large, if the request was successful). Typically, you should store the requested allocation size rather than use this function.
Note the last sentence.

realloc in C — exact behaviour and uses

Reading some literature, I was able to grasp that realloc takes in a void pointer and a size variable and re-allocates the memory of the block the void pointer points to.
What will happen if realloc is called on an integer pointer (int *)
with a size of character? And vice versa.
What can be a possible application of this? (An example would definitely help.)
The realloc() function is the all-in-one memory management system.
If called with a null pointer and a non-zero size, it allocates memory.
If called with a valid pointer and a zero size, it frees memory.
If called with a valid pointer and a non-zero size, it changes the size of the allocated memory.
If you call realloc() with an invalid pointer — one which was not obtained from malloc(), calloc() or realloc() — then you get undefined behaviour.
You could pass realloc() an integer pointer to an allocated space of sizeof(char) bytes (1 byte), but you'd be in danger of invoking undefined behaviour. The problem is not with realloc(); it is with the code that was given an unusable integer pointer. Since only 1 byte was allocated but sizeof(int) is greater than 1 (on essentially all systems; there could be exceptions, but not for someone asking this question), there is no safe way to use that pointer except by passing it to free() or realloc().
Given:
int *pointer = malloc(sizeof(char));
you cannot do *pointer = 0; because there isn't enough space allocated (formally) for it to write to. You cannot do int x = *pointer; because there isn't enough space allocated (formally) for it to read from. The word 'formally' is there because in practice, the memory allocators allocate a minimum size chunk, which is often 8 or 16 bytes, so there actually is space after the one byte. However, your are stepping outside the bounds of what the standard guarantees, and it is possible to conceive of memory allocators that would hand you exactly one byte. So, don't risk it. An integer pointer to a single byte of allocated memory is unusable except as an argument to the memory allocation functions.
The first argument to realloc() is a void *. Since you're going to have a prototype in scope (#include <stdlib.h>), the compiler will convert the int * to a void * (if there's anything to do for such a cast), and as long as the space pointed at was allocated, everything will be fine; realloc() will change the allocation size, possibly returning the same pointer or possibly returning a different pointer, or it will release the space if the new size is zero bytes.
There is a vitally important requirement to non-NULL pointers that you pass to realloc: they must themselves come from a call to malloc, calloc or realloc, otherwise the behavior is undefined.
If you allocate a chunk of memory sufficient to store an int and then realloc for a char, you will always get back the same pointer, because sizeof(char) is less than or equal to the sizeof(int):
int* intPtr = malloc(sizeof(int));
int* otherPtr = realloc(intPtr, sizeof(char));
// intPtr == otherPtr
If you try it the other way around, you will almost certainly get back the same pointer as well, because memory allocators rarely, if ever, parcel the memory to chunks smaller than sizeof(int). However, the result is implementation-dependent, so theoretically you may get back a different address.
As far as the utility of any of the above exercises goes, it is not useful: realloc has been designed with the intention to help you manage variable-sized arrays, simplifying the code for growing the size of such arrays, and potentially reducing the number of allocations and copying. I do not see a reason for realloc-ing a scalar.
The type of the first parameter of realloc is void *, as you said yourself. So the function argument that you pass is converted to a void pointer, which is an implicit and safe conversion.
It's the same as if you called a function with a long int parameter with an int argument, essentially.
Realloc takes the size in bytes. If you do
int* a= malloc(sizeof(int));
and then
a=realloc(a,1);
of course a will now not be big enough for an int type and writing an int in it will give you odd behavior.
As stated by dasblinkenlight, realloc doesn't make sense for a scalar.
In your example:
int * a = malloc(sizeof(int));
int * b = realloc(a,sizeof(char));
Would result in a == b, simply because sizeof(char) < sizeof(int) and there is no reason for moving the data to a new location.
The difference is, that after the realloc you are writing your int to unallocated space, as you decreased the allocated space using realloc. Here this is only of theoretical relevance. Because of alignment it is very unlikely, that the os is reusing the freed memory. But you shouldn't rely on that. This is undefined behavior.
It could become relevant, if you resize the space of a long int to an int. This depends on your architecture.
Writing to unallocated space is like laying a time bomb and not knowing when it will explode. You should only read from / write to allocated space.

Getting array size in C. Cannot understand output

I am curious why I am getting the following behaviour in my code.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int M=24;
int arr[M];
int N=24;
int* ptr=(int*) malloc(sizeof(int)*N); /*Allocate memory of size N */
printf("Size of your malloced array is %lu\n",sizeof(ptr)/sizeof(ptr[0])); /* Get the size of memory alloctaed. Should be the same as N?*/
printf ("Size of your normal arrays is %lu\n",sizeof(arr)/sizeof(arr[0])); /* Ditto */
free(ptr);
return 0;
}
The output is
Size of your malloced array is 2
Size of your normal arrays is 24
I would have thought the output would be 24 in both places. How then does one get the size of the malloced array If somehow I have "forgotten" it?
Surely the pointer ptr will contain some information about the size of the malloced array since when we call free(ptr) it will release the array just malloced
When you use sizeof() on a pointer, you get the size of the pointer. Not the size of the allocated array. In your case, a pointer is probably 8 bytes and an int is 4 bytes, hence why you get 2.
In short, you can't get the size of an allocated array. You need to keep track of it yourself.
EDIT : Note that some compilers do actually support this functionality as an extension:
For example, MSVC supports _msize(): http://msdn.microsoft.com/en-us/library/z2s077bc.aspx
While sizeof() works as you'd expect with fixed-length and variable-length arrays, it doesn't know anything about the sizes of malloc()'ed arrays.
When applied to a pointer, sizeof() simply returns the size of the pointer.
More generally, given a pointer to a malloc()'ed block, there's no standard way to discover the size of that block.
See C FAQ questions 7.27 and 7.28.
In summary, if you need to know the size of a heap-allocated array in a portable manner, you have to keep track of that size yourself.
You cannot obtain, at runtime, the size of an array if you only have a pointer to (the first element of) the array. There are no constructs at all in C that allow you to do this. You have to keep track of the length yourself.
If you happen to have an array rather than a pointer then you can find its length, but not for a pointer to an element of the array.
In your code, ptr is a pointer and so you cannot find out the length of the array to which it points. On the other hand, arr is an array and so you can find out its length with sizeof(arr)/sizeof(arr[0]).
As this other question points out, there is no portable way getting the size of a dynamic array, since malloc may allocate more memory than requested. Furthermore managing malloc requests is up to the operating system. For instance *nix would calls sbrkand store the requests somewhere. So, when you call sizeof(ptr) it returns the size of the pointer and not the size of the array. On the other hand, if your array is fixed, the size of it is determined at compile time, so the compiler is able to replace sizeof(arr) with the size of the fixed array, thus providing you the "correct" size.
The size of a pointer is 4 bytes on 32-bit machines and 8 bytes on 64-bit machines. I guess you work on a 64-bit machine since the size of an int is 4, and you got that sizeof(ptr)/sizeof(ptr[0]) is 2.
The thing to remember about sizeof is that it is a compile-time operator1; it returns the number of bytes based on the type of the operand.
The type of arr is int [24], so sizeof arr will evaluate to the number of bytes required to store 24 int values. The type of ptr is int *, so sizeof ptr will evaluate to the number of bytes required to store a single int * value. Since this happens at compile time, there's no way for sizeof to know what block of memory ptr is pointing to or how large it is.
In general, you cannot determine how large a chunk of memory a pointer points to based on the pointer value itself; that information must be tracked separately.
Stylistic nit: a preferred way to write the malloc call is
int *ptr = malloc(sizeof *ptr * N);
In C, you do not need to cast the result of malloc to the target pointer type2, and doing so can potentially mask a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope.
Secondly, notice that I pass the expression *ptr as the operand to sizeof rather than (int). This minimizes bugs in the event you change the type of ptr but forget to change the type in the corresponding malloc call. This works because sizeof doesn't attempt to evaluate the operand (meaning it doesn't attempt to dereference ptr); it only computes its type.
1 The exception to this rule occurs when sizeof is applied to a variable-length array; since the size of the array isn't determined until runtime, a sizeof operator applied to a VLA will be evaluated at runtime.
2 Note that this is not the case in C++; a cast is required, but if you're writing C++ you should be using new and delete instead of malloc and free anyway. Also, this is only true since C89; older versions of C had malloc return char * instead of void *, so for those versions the cast was required. Unless you are working on a very old implementation (such as an old VAX mini running an ancient version of VMS), this shouldn't be an issue.

Resources