Here is the code I'm using:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
int i;
for (i = 0; i < sz; ++i) {
if (arr[i] != 0) {
printf("OK\n");
break;
}
}
free(arr);
return 0;
}
The program doesn't print OK. malloc isn't supposed to initialize the allocated memory to zero. Why is this happening?
malloc isn't supposed to initialize the allocated memory to zero. Why is this happening?
This is how it was designed more than 40 years ago.
But, at the same time, the calloc() function was created that initializes the allocated memory to zero and it's the recommended way to allocate memory for arrays.
The line:
arr = (int *)malloc(sz * sizeof(int));
Should read:
arr = calloc(sz, sizeof(int));
If you are learning C from an old book it teaches you to always cast the value returned by malloc() or calloc() (a void *) to the type of the variable you assign the value to (int * in your case). This is obsolete, if the value returned by malloc() or calloc() is directly assigned to a variable, the modern versions of C do not need that cast any more.
The man page of malloc says:
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that can
later be successfully passed to free().
So malloc() returns uninitialized memory, the contents of which is indeterminate.
if (arr[i] != 0)
In your program, You have tried to access the content of a memory block, which is invoked undefined behavior.
malloc isn't supposed to initialize the allocated memory to zero.
Memory allocated by malloc is uninitialised. Value at these locations are indeterminate. In this case accessing that memory can result in an undefined behavior if the value at that location is to be trap representation for the type.
n1570-ยง6.2.6.1 (p5):
Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. [...]
and footnote says:
Thus, an automatic variable can be initialized to a trap representation without causing undefined behavior, but the value of the variable cannot be used until a proper value is stored in it.
Nothing good can be expected if the behavior is undefined. You may or may not get expected result.
From the C Standard 7.22.3.4:
Synopsis
#include <stdlib.h>
void *malloc(size_t size);
Description
The malloc function allocates space for an object whose size is
specified by size and whose value is indeterminate.
The value is indeterminate. So, every compiler is free to behave how it wants. For example, in Microsoft Visual C++, in Debug mode, the area of allocated memory by malloc() is all set to 0xCDCDCDCD and when in Release mode it is random. In modern versions of GCC, it is set to 0x000000 if you don't enable code optimizations, and random otherwise. I don't know about other compilers, but you get the idea.
void *malloc(size_t size) is just supposed to keep aside the specified amount of space. That's all. There is no guarantee as to what will be present in that space.
Quoted from the man pages:
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that can
later be successfully passed to free().
Apart from calloc() you can use the memset() function to zero out a block of memory.
The first time you call malloc(3), it asks to the operating system to get memory for the heap space.
For security reasons, the unix/linux kernel (and many other operating systems) in general zeroes the page contents that is to be given to a process, so no process can access that memory's previous contents and do nasty things with it (like searching for old passwords, or similar things).
If you do several allocations and deallocations of memory, when the malloc module reuses the previous memory, you'll see garbage coming from malloc(3).
Zero's are assigned to page contents at first time in linux kernel.
Below program explains the memory initialisation difference in malloc and calloc:
#include<stdio.h>
#include<stdlib.h>
#define SIZE 5
int main(void) {
int *mal = (int*)malloc(SIZE*sizeof(int));
int *cal = (int*)calloc(SIZE, sizeof(int));
mal[4] = cal[4] = 100;
free(mal); free(cal);
mal = (int*)malloc(SIZE*sizeof(int));
cal = (int*)calloc(SIZE, sizeof(int));
for(int i=0; i<SIZE; i++) {
printf("mall[%d] = %d\n", i, mal[i]);
}
for(int i=0; i<SIZE; i++) {
printf("call[%d] = %d\n", i, cal[i]);
}
}
I use malloc to allocate everything from the heap(dynamic memory) while i should use calloc instead nowaday , and memset is great for filling you memory segment with any chosen character.
Compile and work great with GCC:
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
int main()
{
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
memset(arr, 0, sz*sizeof(int) );
int i;
for (i = 0; i < sz; ++i) {
if (arr[i] != 0) {
printf("OK\n");
break;
}
}
free(arr);
return 0;
}
ref: http://www.cplusplus.com/reference/cstring/memset/
well, the value is not initialized in malloc.
And it does print "OK" in VS Code.
so in VS Code, the output is : "OK" followed by a garbage value.
in a web based compiler (here's the link : https://www.programiz.com/c-programming/online-compiler/ ),
the output was
"LOL" followed by '0'
so some compilers do initialize the value..but actually the value in malloc is not intialized. so it will return a garbage value when printed as in the above example in VS Code.
int main()
{
int *arr;
int sz = 100000;
arr = (int *)malloc(sz * sizeof(int));
int i;
for (i = 0; i < sz; i++)
{
if (arr[i] != 0)
{
printf("OK\n");
break;
}
else
{
printf("LOL \n");
break;
}
}
printf("%d", arr[0]);
free(arr);
Related
I've written the following simple program that sums up the numbers from 0 to 9:
#include <stdio.h>
#include <stdlib.h>
int* allocArray() {
int arr[10];
return arr;
}
int main(void){
int* p;
int summe = 0;
p = allocArray();
for(int i = 0; i != 10; ++i) {
p[i] = i;
}
for(int i = 0; i != 10; ++i) {
summe += p[i];
}
printf("Sum = %d\n", summe);
}
The code compiles and delivers the expected result "45". However I get the following warning: 'address of stack memory associated with local variable
'arr' returned'. What am I doing wrong?
This is undefined behaviour, plain and simple. The only reason it "works" is because with this particular compiler the stack hasn't been trashed yet, but it is living on borrowed time.
The lifetime of arr ends immediately when the function call is complete. After that point any pointers to arr are invalidated and cannot be used.1
Your compiler uses stack memory to store local variables, and the warning indicates that you're returning an address to a now-invalidated stack variable.
The only way to work around this is to allocate memory dynamically and return that:
int* allocArray() {
int* arr = calloc(10, sizeof(int));
return arr;
}
Where you're now responsible for releasing that memory later.
You can also use static to extend the lifetime of arr:
int* allocArray() {
static int arr[10];
return arr;
}
Though this is not without consequences, either, as now arr is shared, not unique to each function call.
1 Like a lot of things in C there's significant overlap between what you "cannot do" because they lead to undefined behaviour and/or crashes and what you "can do" because it's permitted by the syntax and compiler. It's often your responsibility to know the consequences of any code you write, implied or otherwise.
To keep it in your code:
int arr[10];
will allocate the memory on the stack. As soon as you are leaving the function, the content of that array will be overwritten pretty soon. You want to allocate this on the heap.
You would need to use
int* arr = malloc(sizeof(int)*10);
and in the main function, after you've used it (at the end of main), call
delete[] arr;
Nevertheless, this code could be better if the ownership of the array would be properly handled. You want to make yourself familiar with C++ containers and shared/unique pointers.
How can I allocate memory on the stack and have it point to different memory addresses so I can use it later? For example. this code:
for (int i = 0; i < 5; i++) {
int nums[5];
nums[0] = 1;
printf("%p\n", &nums[0]);
}
Will print out the same address every time. How can I write memory to stack (not the heap, no malloc) and have it not overwrite something else that's on the stack already.
You could use alloca to allocate a different array from the runtime stack for each iteration in the loop. The array contents will remain valid until you exit the function:
#include <stdlib.h>
#include <stdio.h>
void function() {
for (int i = 0; i < 5; i++) {
int *nums = alloca(5 * sizeof(*nums));
nums[0] = 1;
printf("%p\n", (void *)nums);
/* store the value of `num` so the array can be used elsewhere.
* the arrays must only be used before `function` returns to its caller.
*/
...
}
/* no need to free the arrays */
}
Note however that alloca() is not part of the C Standard and might not be available on all architectures. There are further restrictions on how it can be used, see the documentation for your system.
I believe you are looking for:
a way to control how memory is being allocated on the stack, at least in the context of not overwriting already-used memory
Of course, that's taken care by the OS! The low level system calls will make sure that a newly created automatic variable will not be written upon an already used memory block.
In your example:
for (int i = 0; i < 5; i++) {
int nums[5];
...
}
this is not the case, since nums will go out of scope, when the i-th iteration of the for loop terminates.
As a result, the memory block nums was stored into during the first iteration, will be marked as free when the second iteration initiates, which means that when nums of the first iteration is going to be allocated in the stack, it will not be aware of any existence of the nums of the first iteration, since that has gone already out of scope - it doesn't exist!
How can I let the user choose a number say n and then create an array with the size of n?
Can I just say int a[]=malloc (n*sizeof(int))?
There are two ways to do that. If the array size is small then you can use variable length array
/* Valid in C99 and later */
int n;
scanf("%d", &n);
int a[n];
This will allocate memory on stack. Other way is you can use dynamic memory allocation which will allocate memory on the heap
int *a = malloc(n*sizeof(int));
Your idea is nearly correct:
int a[] = malloc(n*sizeof(int));
Using malloc is the correct way.
But you cannot assign the returned address to an array.
You must use a pointer variable instead:
int *a = malloc(n*sizeof(int));
Yes if u want to set the size of the array at run-time.
Then u should go for dynamic memory allocation(malloc/calloc).
int a[]=malloc (n*sizeof(int));//this not possible.
int *a =malloc (n*sizeof(int)); // this is possible.
There are two basic ways for allocating the memory to create an array where the size to the array is determined as input:
The first one is,
allocating the memory for array in the 'stack' segment of memory where the size of array is taken as input ant then the array of that particular size is defined and granted memory accordingly.
int n;
scanf("%d",&n); //scanning the size
int arr[n]; //declaring the array of that particular size here
The second one is,
allocating the required memory in the 'heap' segment of memory.It is the memory allocated during runtime (execution of the program)
So,another way of declaring an array where size is defined by user is
int n,*arr;
scanf("%d",&n);
arr=malloc(n*sizeof(int)); //malloc function provides a contiguous space
or
arr=calloc(n,sizeof(int)); //calloc function is similar,initializes as 0
to use both these functions make sure to include stdlib.h.
Variable length arrays (VLAs) were added to C with C99, but made optional with C11. They are still widely supported, though. This is the simplest way to define an array with user-selected size at runtime.
Other than that VLAs may not be available on all platforms, they also may fail silently when there is an allocation failure. This is a disadvantage that malloc() avoids when used correctly.
You can't assign to an array in C, and instead you need to store the value returned by malloc() in a pointer. Note that malloc() returns NULL when there is an allocation failure, allowing code to check for failure and proceed accordingly. The actual allocation might look like this:
int *a_dyn = malloc(sizeof *a_dyn * arr_sz);
This is an idiomatic way of calling malloc(). Note that there is no need to cast the result of malloc(), and note that the operand to sizeof is not an explicit type, but rather an expression involving a_dyn. The sizeof operator uses the type of the expression *a_dyn, which is in fact int (there is no dereference made). This is less error-prone and easier to maintain when types change during the life of a program than coding with explicit types. Also note that the sizeof expression comes before arr_sz. This is a good practice to follow: sometimes you might have a call like:
int *arr = malloc(sizeof *arr * nrows * ncols);
Placing sizeof first forces the multiplication to be done using size_t values, helping to avoid overflow issues in the multiplication.
Don't forget to free any memory allocated with malloc() when it is no longer needed, avoiding memory leaks.
Whether you use a VLA or malloc(), you must validate user input before using it to avoid undefined behavior. Attempting to allocate an array of non-positive size leads to undefined behavior, and attempting to allocate too much memory will lead to an allocation failure.
Here is an example program that illustrates all of this:
#include <stdio.h>
#include <stdlib.h>
#define ARR_MAX 1024 // some sensible maximum array size
int main(void)
{
int arr_sz;
int ret_val;
/* validate user input */
do {
printf("Enter array size: ");
ret_val = scanf("%d", &arr_sz);
} while (ret_val != 1 || arr_sz < 1 || arr_sz > ARR_MAX);
/* use a VLA */
int a_vla[arr_sz];
for (int i = 0; i < arr_sz; i++) {
a_vla[i] = i;
printf("%d ", a_vla[i]);
}
putchar('\n');
/* use malloc() */
int *a_dyn = malloc(sizeof *a_dyn * arr_sz);
if (a_dyn == NULL) { // malloc failure?
fprintf(stderr, "Unable to allocate memory\n");
} else { // malloc success
for (int i = 0; i < arr_sz; i++) {
a_dyn[i] = i;
printf("%d ", a_dyn[i]);
}
putchar('\n');
}
/* avoid memory leaks */
free(a_dyn);
return 0;
}
I am just curious about how memory leaks happens when you write a C program.
Are the following are examples of memory leaks?
Trying to access the part of the memory whose access is not given to your program or when you are trying to access the location of the array which is not there.
#include <stdio.h>
int main(void)
{
int num[5];
int i;
for(i=0;i<5;i++)
scanf("%d", (num+i));
printf("%d\n", num[5]); //printing the data stored at loc num[5] which is not present.
return 0;
}
Printing the value stored in an un-initialized variables.
Use of void*memcpy(const*dst,void const*src,size_t n) function memory leak occurs when src and dst pointers points to the same memory address or function is undefined when addresses overlaps.
Use of free() more than once on the same pointers which has been freed already. For Example:
#include <stdio.h>
int main(void)
{
int*num = NULL;
int i;
num = (int*) calloc(sizeof(int), 5);
for (i = 0; i < 5; i++)
scanf("%d", (num + i));
free(num);
free(num);
return 0;
}
All of aforesaid scenarios cause undefined behavior.
printf("%d\n", num[5]); is out-of-bound memory access.
Printing the value stored in an un-initialized variables, in case of the variable has trap representation, causes UB.
Source and destination overlap in memcpy(), UB.
Multiple free() is also UB.
Also, memory leak is not about any invalid access, it is just wastage of memory leading to out of memory scenario for a system. You can read more about that here.
My problem is that i am not sure how to allocate memory properly. I have researched it but to no avail. Some help regarding malloc would be great.
int main(int argc, char *argv[]) {
int i, a[5000], c = 1, m, n, input;
scanf("%d", &input);
for (i = 0; i <= 9999; i += 2) {
a[c] = i;
c++;
}
for (n = 2; n < 1118; n++) {
for (m = a[n]; m < a[5000]; m++) {
a[m] = a[m+1];
}
}
printf("%d", a[input]);
free (*a);
return 0;
}
'a' is allocated on stack therefore no need to free it.
You only need to free variables allocated by *alloc family of functions.
First of all, C arrays have 0-based indexing. By setting the intial value of c to 1 and then using as index inside the loop, you're going off-by-one. This invokes undefined behavior.
After that, you don't need to do free (*a);, a is an array, not a pointer returned by a memory allocator functions, malloc() or family.
That said, in this code, *a does not give you a pointer, at all, it is same as a[0] which is of type int.
Finally, without any bound checking from user supplied value of input, using a[input] may very well be accessing out of bound memory, causing UB.
FWIW, passing a pointer to free() which is not returned previously by malloc() and family also invokes undefined behavior.
malloc takes one argument - the number of bytes to allocate. It returns a void pointer (which is a pointer to a section of memory that can hold any data type).
Here's an example.
int *array = malloc(sizeof(int) * 10);
This allocates a 10-element array of integers. Note it leaves your data uninitialized, so the contents of the array are undefined. There's a function called calloc that does initialize it to zeros.
Also, a style tip. You might try to cast the result of a malloc call to a pointer for the type of data you will store in it (for example, int *array = (int *)malloc(sizeof(int) * 10);. This is frowned upon by C programmers for reasons explained in this post.