App crashes while printing array after free() - c

Why does it crash while trying to printf() after having free()?
I've created dyanmic array. Displayed elements. Filled each elements with value. Then freed memory using free(). And then trying to display elements again.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
int *p;
p = (int *)malloc(10 * sizeof(int));
for ( i = 0; i < 10; i++ )
printf("%d ", p[i]);
printf("\n");
for ( i = 0; i < 10; i++ )
p[i] = i;
for ( i = 0; i < 10; i++ )
printf("%d ", p[i]);
printf("\n");
free(p);
p = NULL;
for ( i = 0; i < 10; i++ ) /* App crashes around here. */
printf("%d ", p[i]);
printf("\n");
return 0;
}
P.S. I'm new to C.
Let me know what is wrong, please.

Because you reference memory pointing to NULL.
This is actually undefined behavior so it might work, but dereferencing a NULL pointer most likely will cause a crash.
Even if you don't set the pointer to NULL it's still undefined behavior to derreference unallocated memory, and although it most likely won't crash it's still a bad thing to do.

When you free any memory, its gone. You can not use it any more.
You should free the after you are done with it.
You are using the pointer p after you have freed it. The system assumes you do not need the memory once you free it. So it does not reserve it for you. It may work some times if the memory is still unused. But in this case you are assigning NULL to the pointer p and then trying to print the value present there, which is definitely not going to work.

One thing always to be remembered.. A freed memory can return the expected result (it sometimes does). Me too sometimes suffered with the problem.. U can finde useful insight here:
Can a local variable's memory be accessed outside its scope?
Now come to your code:
free(p);
Here you may get your expected things..but u r not guaranteed and r not permitted to use this. It is undefined behaviour. But now
p = NULL;
is something that is crashing your program. Because the pointer now points to NULL, and it is not permitted to de-reference a NULL pointer. Do not point to NULL if you don't actually need it. And never ever de-reference a NULL pointer.

Related

C - Avoiding warning "address of stack memory associated with local variable returned"

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.

malloc() fails to allocate memory inside a function in C

I want to allocate memory dynamically inside a function. The function is named func_1 and is declared as follows:
int func_1(int **destination);
Here destination is a pointer to a pointer. This pointer contains the address of the pointer to which I want to allocate memory dynamically inside the function.
The function func_1 has the following code:
void func_1(int **destination)
{
*destination = (int*)malloc(sizeof(int) * 10);
for(int i = 0 ; i < 10 ; i++)
{
*destination[i] = i; //segmentation fault comes HERE
}
}
Below is my main() function:
int main()
{
int *pointer;
func_1(&pointer);
return 0;
}
When I try to run this program, I get a segmentation fault (SIGSEGV) error. I used GDB to locate the source of this fault, and it turned out that the line inside the for loop is the culprit for this error.
Please note that I wish to retain the values I have assigned to the dynamically allocated memory inside the function, once the function exits, and that's the reason due to which I have passed the address of the pointer to which I want to allocate memory dynamically.
I want to know:
Why am I getting this error ?
How can this be fixed ?
Thanks for help !
[] (array subscripting) operator has precedence 2
* (dereference) operator has precedence 3
In your code *destination[i] means the same as *(destination[i]). This value is uninitialized and it leads to segmentation fault.
If you will use explicit priority of operation (*destination)[i] you will get the expected result.
void func_1(int **destination)
{
*destination = (int*)malloc(sizeof(int) * 10);
for(int i = 0 ; i < 10 ; i++)
{
(*destination)[i] = i; //no segmentation fault
}
}
you can read more about precedence here
Full code:
#include <stdio.h>
#include <stdlib.h>
void func_1(int **destination)
{
*destination = (int*)malloc(sizeof(int) * 10);
for(int i = 0 ; i < 10 ; i++)
{
(*destination)[i] = i;
}
}
int main()
{
int *pointer;
func_1(&pointer);
return 0;
}
Why am I getting this error ?
You are overwriting the destination pointer instead of assigning the value returned by malloc to the pointer pointed to by the destination pointer.
Instead of *destination = (int*)malloc(sizeof(int) * 10) you should type **destination = malloc(sizeof(int) * 10).
Instead of *destination[i] = i you should type (**destination)[i] = i.
In C, the array subscript operator [] has a higher precedence than the indirection operator *. In addition to that, the former is left-to-right associative, while the latter is right-to-left associative.
In your case this means that you need to type (**destination)[i] = i; instead of **destination[i] = i, because otherwise the [i] will be evaluated before the ** and you end up indirecting a wild pointer (which will cause a segmentation fault extremely likely in the general and absolutely certainly in this case, since you are referencing a null pointer when i == 0).
How can this be fixed ?
The "just make it work" fix is the one I presented above.
However, that does not address the fundamental issue with your code, which is that it is unnecessarily complicated. Using a pointer to a pointer is very error-prone and should be avoided. Indeed, there is no need to use one at all in this case.
The following does exactly what you want without all the unnecessary complexity:
int* func_1()
{
int* destination = malloc(sizeof(int) * 10);
for (int i = 0; i < 10; ++i)
{
destination[i] = i;
}
return destination;
}
int main()
{
int* pointer = func_1();
free(pointer);
return 0;
}
Please note that I wish to retain the values I have assigned to the dynamically allocated memory inside the function, once the function exits, and that's the reason due to which I have passed the address of the pointer to which I want to allocate memory dynamically.
As I demonstrated above, there is no reason to pass a pointer to the pointer to the function. Memory allocated with malloc is yours to use forever , you just need to keep track of it and release it with a call to free when you no longer need it. How you keep track of the memory doesn't matter - simply returning a pointer is enough in this case. Modifying pointer inside func_1 rather than catching the function's return value provides no additional benefit and only serves to make the code more complicated than it needs to be.
I get the impression that you are somewhat confused about pointers, so I recommend that you revise the subject. Here is a quite clear explanation regarding pointers that also covers pointers to pointeres (and pointers to pointers to pointers): How do pointers work in C?
Read more:
Operator Precedence and Associativity in C
What is a segmentation fault?

Freeing elements of a void pointer array

I am debugging some code written by someone else which has several memory leaks detected by Valgrind. Part of the code which I believe is causing the problems involves void pointers:
int noElements = 100;
void** ptr = malloc( noElements * sizeof(void*));
for(int i = 0; i < noElements; i++)
{
ptr[i] = malloc(sizeof(void*));
}
//Operation filling the array and doing calculation
free(ptr); //This will not clear the underlying array causing the memory leak?
I created a small test program to check the error is where I thought it was (not freeing each ptr[i] before calling free(ptr);), but I am getting errors when trying to free elements. My test program looks like this:
int main()
{
int num = 10000000; //Large array so I can clearly see memory usage
void** ptr = (void**) malloc(sizeof(void*) * num);
for (int i = 0; i < num; i++)
{
ptr[i] = malloc(sizeof(void*));
ptr[i] = &i; //If I never point elements at anything, this code works
}
for (int i = 0; i < num; i++)
{
free(ptr[i]); //Crashes here if the elements have been pointed at a variable
}
free(ptr);
return 0;
}
Why would calling free on each array element cause the program to crash if the pointers have actually been assigned?
In your code
ptr[i] = &i;
creates three issues.
It makes the actual returned pointer by malloc() to be lost (you're overwriting it), so you have no shot at free()-ing it later, leading to memory leak.
i is a local scoped variable (the scope of for loop body), and you're storing the address of the variable to be used outside the scope (i.e., after the lifetime is over). Outside the scope attempt to access the address of it will invoke undefined behavior.
(Ignoring point 2) Attempt to free() the ptr[i] will cause undefined behavior again, as the pointer is not returned by memory allocator function.
Your pointers have been assigned a value which is not what you want.
for (int i = 0; i < num; i++)
{
ptr[i] = malloc(sizeof(void*));
ptr[i] = &i; //If I never point elements at anything, this code works
}
First you assign a valid memory address that is returned by malloc().
This address could be free'd using free().
But then you assign another address. The address of your local variable i. This memory location was not allocated using malloc() and hence cannot be free'd. By assigning this address you've lost the dynamically allocated address causing a memory leak.
Your comment is wrong. You already assigned a value that ptr[i] points to some valid address. You don't need to assign again. And you should not.

Getting a segmentation error in c

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.

In C, memory allocating fails, why?

int x;
int komsuSayisi;//adjanceny matrix
int **arkadas;
int t;
int komsu[24][24];
scanf("%d",&t);
**arkadas = (int **)malloc( t*sizeof( int* )); //allocating rows
for(i=0; i<t; i++)
{
x=0;
arkadas[i] = (int *)malloc( t*sizeof(int) ); //allocating cow temporarily
for(j=0; j<t; j++)
{
komsu[i][j]=fark(kelime[i],kelime[j]); //fark returns 1 or 0.
//so i put those 1 ones to another matrix,arkadas
if(komsu[i][j]==1){
komsuSayisi++;
arkadas[i][x]=j;
x++;
}
arkadas[i] = (int *) realloc(arkadas[i], x);
//real allocating here
}
It gives error and shut downs.There is nothing wrong. What i want is adjanceny is too big to search so i will easily search the "1" ones with this matrix.
**arkadas = (int **)malloc( t*sizeof( int* ));
should be
arkadas = malloc( t*sizeof( int* ));
**arkadas dereferences an uninitialised pointer, resulting in you trying to write to an unpredictable address. You don't own the memory at this address so it isn't safe to try and write to it.
The second form assigns the address of an array of pointers to the local variable arkadas; this is what need to do.
Later in your program
if(komsu[i][j]==1){
komsuSayisi++;
arkadas[i][x]=j;
x++;
}
arkadas[i] = (int *) realloc(arkadas[i], x);
code inside the if condition attempts to write to arkadas[i] before you allocate it. This also invokes undefined behaviour and will likely crash. You can avoid the crash by removing the line arkadas[i][x]=j; and swapping your realloc call for malloc (you need the address of a previous allocation before you can call realloc)
if(komsu[i][j]==1){
komsuSayisi++;
x++;
}
arkadas[i] = malloc(x*sizeof(int));
I see
komsuSayisi++;
You didn't paste the whole code but probably thats what is crashing your program... I don't see any initializing previous to that increment....
this plus the deferentiation posted on the other answer

Resources