Invalid memory reference and pointer problem - c

The question is to receive a new number and sort all in descending order.I want to combine old with new number ,put them to a new array.and then sort them.I took a long time to handle with it but failed.SOS! What is the problem?😑
int* fun(int* a, int num){
int pa[7];
for(int i=0;i<5;i++){
pa[i]=a[i];
}
pa[6]=num;
swap(pa,7);
return pa;
}
void swap(int *pa,int n)
{
int i,j,t;
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++)
{
if(*(pa+i)>*(pa+j))
{
t=*(pa+i);
*(pa+i)=*(pa+j);
*(pa+j)=t;
}
}
}
}
int main(){
int a[7]={86,89,23,34,11,87};
int num;
scanf("%d",&num);
int *pa=fun(a,num);
for(int i=0;i<7;i++)
printf("%d ",*(pa+i));
return 0;
}

The pa in your fun() is a local variable to it. This means that anything concerned with pa is freed when your function returns. If you want to return a newly formed array, use dynamic memory allocation with the aid of malloc() or calloc() functions and not simply an array you create and pass a reference of.
Sometimes, you may get the contents you expect from such a return, but it is not certain as the memory you are returning is now free to be reused and can be overwritten. The contents of the pa in fun() after returning are not guaranteed.

Function variables are created in the stack. After the execution of the function ends, all of its variables are "removed" from stack. So you can't access them outside the function. For example,
int* f(){
int x = 5;
int* a = &x;
return a;
}
This function will return the address of x but that address will be an invalid address because the variables x, a cease to exist after the execution of the function ends.
How to get around it?
Store the data in the heap. The stack is cleared after the execution of the function ends but heap is not cleared, so you can store something in the heap and access it later from anywhere anytime.
int* fun(){
int*x = (int*)malloc(sizeof(int)); // allocates 4 byte memory in the heap.
*x=5;
return x;
}
int main(){
int* check = fun();
printf("Value: %d\n",*check);
}

Related

Where is the error in this function to print a random array?

I don't understand where the error is in the function.I need to print 2 arrays with random elements.
int *boo3(int *x , int n){
x = (int*) malloc(sizeof(int)*n);
int i;
for(i=0;i<n;i++){
x[i] = rand()%10-(rand()%10);;
printf("%5d ",x[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
int *x ,*y;
int n , m;
int i,j;
printf("enter size of X[n]: ");
scanf("%d",&n);
printf("enter size of Y[m]: ");
scanf("%d",&m);
x=boo3(*x,n);
y=boo3(*y,m);
free(x);
free(y);
return 0;
}
There are several problems with this code:
x = (int*) malloc(sizeof(int)*n); overwrites the function parameter x.
No return statement in boo3,
x=boo3(*x,m) in this line, *x is dereferencing pointer x which gives you int
In main function, you tried to free uninitialized pointer x and y
In your code
int *boo3(int *x , int n)
This indicates that you should receive a return value from this function.
In general a return value can be error code or any data which you might want to use going ahead.
Just like a math function for addition, taking operands as an argument and returning the sum. In your case, it is a pointer to the memory you have been allocated with.
In boo3() function, you are allocating some memory and you need the pointer to that memory for further usage. boo3() doesn't return anything, however, in main() function, you are assuming that you have caught it, hence the problem.
You should return the pointer to data from boo3().
I can see in main() function,
x=boo3(*x,n);
This is alarming. You are dereferencing a int* pointer and passing an int (instead of int*) as an argument to boo3() function which expects a int*.
If you wish to assign the pointer declared in main() with the address of memory allocated in boo3(), then you don't catch it and change to
boo3(x, n);
boo3(y, m);
And change to
void boo3(int *x , int n)
However, ideally, the function should return and the value be caught as a return value. In that case, change to
int* boo3(int n)
At the end of boo3 add a return x;. And use it as
x = boo3(n);
Additionally, you are not checking if the malloc() has allocated any memory or not. You should check if the pointer is NULL to see if memory is allocated. It is minimum error-checking and handling you need to have. Secondly, malloc() returns a void*, so the typecast is needless.
The problem is, you do not return anything from the function boo3(), and try to use the return value. This causes undefined behavior.
You need to add a return x; at the end of the function so as to return the pointer holding the address of the allocated memory (and populated values).
That said, passing the pointer argument is not needed when you return the pointer from the function. Apart from the fact that your call does not even try to pass a pointer as the first argument, as expected by the function signature - to allocate memory to a pointer from a called function, you need to pass the address of the pointer anyways, passing the pointer alone will not suffice. You don't need to do that, just define the function as
int *boo3(int n) { //......
and in the end, add
return x;
and from main(), call it like
x=boo3(n);
y=boo3(m);
There are many issues in your code.
Following has been corrected:
boo3 now simply returns the pointer to the allocated memory filled with random numbers, the useless x parameter has been removed and the function now contains the missing return statement. This is actually the main problem in your code.
The pointless (int*) cast has been removed from malloc.
The code is formatted properly.
Variables are declared as close as possible to their scope. This is the idiomatic way, declaring all variables at the start of the scope is a thing from the last century.
Usage of meaningful variable names.
This is a correct version of your program:
#include <stdlib.h>
#include <stdio.h>
int* boo3(int n) {
int *array = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
array[i] = rand() % 10 - (rand() % 10);;
printf("%5d ", array[i]);
}
printf("\n");
return array;
}
int main(int argc, char* argv[])
{
int sizex, sizey;
printf("enter size of X[n]: ");
scanf("%d", &sizex);
printf("enter size of Y[m]: ");
scanf("%d", &sizey);
int *xvalues = boo3(sizex);
int *yvalues = boo3(sizey);
free(xvalues);
free(yvalues);
return 0;
}
Disclaimer: for brevity there is no error checking for scanf and malloc.

What is the difference between returning a pointer to a calloced int and returning the address of a initialized int in a function?

I'm interested the difference between these two scenarios:
int *function() {
int i = 5;
return &i;
}
and
int *function() {
int *i = calloc(1, sizeof(int));
*i = 5;
return i;
}
is there a difference? If so, can someone explain what is going on in the background?
Yes there is a difference. In the first scenario, the integer i is being allocated on the stack, which means it will get reused when the function returns. In the second scenario, the memory is being allocated on the heap and will not get overwritten outside of the function call.

C Returning an array from a function

And having some trouble grasping arrays in C and how to return them via a function. If I do something like this
int main()
{
int num_set[10]={0,1}; //initialize first two elements as 0,1 and rest as 0
int* p=num_set; //assign array to int pointer called p
printf("\n%i",&num_set); //outputs 2686660 on my machine
printf("\n%i",&num_set[0]); //also outputs 2686660
printf("\n%i",p); //also outputs 2686660
printf("\n%i",p[1]);* //outputs 0; the same as num_set[1]
}
It works as expected, but when I try to return an array through another function like the following
int multiply_by_2(int given_number)
{
int num_set[10];
for(int fun_counter=0; fun_counter<10; fun_counter++)
{
num_set[fun_counter] = (given_number*2) ;
}
return num_set; //return int array num_set to caller
}
int main()
{
int* p = multiply_by_2(300) //assign array returned by function to p
for(int main_counter=0; main_counter>10; main_counter++)
{
printf("\np[%i] = %i"
, i, p[i]);
}
}
I get an error saying "invalid conversion from 'int' to 'int*'"
They was no error when I assigned the array to an int pointer in the first code, but I get this error when I try to return it through a function.
Please help.
In C you cannot return array by value. You would have to return the pointer of the array you want to return.
Pass a pointer and a size for a buffer to store your results.
There are a number of errors here.
The return type of the function multiply_by_2 needs to be int* - i.e a pointer to an integer. What is actually returned is a pointer to the first element of the array.
You are attempting to return a variable initialized on the stack (num_set). This will
disappear as soon as the multiply_by_two function exits, because it is an automatic variable. Instead, you should use the malloc function to allocate heap memory. Here's a link explaining the difference between stack and heap memory
You have a > where you should have a < in the for loop in main. As written the loop will immediately exit.
Minor point - the number 10 is repeated several times throughout the code. It is better practice to use a variable or a #define to give the number a meaningful name
Here's an amended version of the code:
#include <stdio.h>
#include <stdlib.h> //This is required to use malloc
#define ARRAY_SIZE 10
int* multiply_by_2(int given_number)
{
int *num_set =malloc(sizeof(int)*ARRAY_SIZE);
for(int fun_counter=0; fun_counter<ARRAY_SIZE; fun_counter++)
{
num_set[fun_counter] = (given_number*2) ;
}
return num_set; //return int array num_set to caller
}
int main()
{
int* p = multiply_by_2(300); //assign array returned by function to p
for(int i=0; i<ARRAY_SIZE; i++)
{
printf("\np[%i] = %i", i, p[i]);
}
free(p);
}
This is wrong on so many levels, but the compiler error comes from your declaration of "multiply_by_2". You declare it to return an integer, but then you try to return a pointer.
Let's try something like this:
int* multiply_by_2(int size, int given_number)
{
int *ip = (int*)malloc(size*sizeof(int)); // dynamically create int x[size]
for(int fun_counter=0; fun_counter < size; fun_counter++)
{
ip[fun_counter] = (given_number*2) ;
}
return ip; //return int array num_set to caller
}
Caller must free() returned memory.
int main(int argc, char **argv) {
int *ip = multiply_by_2(3, 2);
// ip points to array {4, 4, 4}
free(ip);
return 0;
}
We say that the function caller becomes owner of returned memory, that's why you are responsible to call free() later.
int multiply_by_2(int given_number) // not returning an array, but just an int
The return type of your function is int therefore you will get an error when trying to assign it to int *. Change it to the following:
int* multiply_by_2(int given_number)
This change is acceptable because in C, an array of ints is interchangeable with a pointer to an int.
Your header is wrong. Should be
int* multiply_by_2(int given_number)
You need to return pointer of int, not just int.
Another thing, in the function multiply_by_2 you have created local array. That means that the array will be deleted after the function will end.
You must use dynamic allocation (malloc and free).
Three major problems in your program:
The return type of function is int but you are returning an int * type.
You are returning the pointer to an automatic local variable.
Second expression in for loop in main would not let the body of loop to execute.
Change return type of the function to int * and use dynamic allocation.
int* multiply_by_2(int given_number)
{
int* num_set = malloc(sizeof(int)*10);
// rest of you code
}
And finally change second expression in your for loop in main to main_counter < 10. Use free in main to free the allocated memory.

what will be the output of the following snippet?

what's happening after clrscr?
#include<stdio.h>
#include<conio.h>
int *call();
void main()
{
int *ptr;
ptr=call();
clrscr();
printf("%d",*ptr);
getch();
}
int*call()
{
int a=25;
a++;
return &a;
}
output:
-10
code works like this:
call() is called, a=25, then a=26. let address of a be 65518. this address is returned to ptr. since return type is int, instead of 65518, (due to cyclic property) -18 is returned.
so ptr=&a=-18. then clrscr clears it....but how *ptr is printed as output? i mean address cannot be negative(-18).
Returning a pointer to local is undefined behavior. Anything could happen - your program could crash, but more likely it is going to print some arbitrary number.
If you need to return a pointer from a C function, you need to either allocate a memory block in the dynamic storage, like this:
int*call()
{
int *a=malloc(sizeof(int));
*a = 25;
*a++;
return a;
}
or use a pointer to a statically allocated block, like this:
int* call()
{
static int a=25;
a++;
return &a;
}
If you choose the dynamic allocation route, the caller must free the pointer returned by your function.
int*call()
{
int a=25; // <--- use malloc here i.e. int a = malloc(sizeof(int)); then you can set a value to a and return the pointer without any problemk, OTHERWISE => it will return an address of some random junks you don't want, its gonna be completely random
a++;
return &a;
}
When call() is called, a new stack frame is created with space for the local variable a, which has its lifetime during the execution of call(). When it returns, the stack frame is removed along with its local variable(s) and data. Trying to use this data outside the function is undefined, because it no longer exists, logically.
If you want to declare a inside a function and use it afterwards, you'll need to allocate it:
...
int *a = malloc(sizeof int);
*a = 26;
return a;
...
Remember to free() this pointer after you're finished using it.

Scope of malloc used in a function

When a function returns, is the memory allocated via malloc freed? Or can it still be accessed in the main() function using pointers?
eg.
void function(int *a)
{
a=(int *)malloc(sizeof(int));
*a=10;
}
int main()
{
int *num;
function(num);
printf("%d",*num);
return(0);
}
Can the integer stored in a be accessed by main() here?
No, the memory allocated with malloc is not freed when you leave the scope/return from the function.
You're responsible for freeing the memory you malloc.
In your case though, the memory is NOT accesible in main(), but that's because you only deal with a local variable.
void function(int *a)
{
a=(int *)malloc(sizeof(int));
Here, a is a local variable within function . Pointers are passed by value in C, so a receives a copy of the pointer in main when you do function(num); main() does not see that you assign to that local copy of the pointer.
You have to do either:
void function(int **a)
{
*a= malloc(sizeof(int));
**a=10;
}
int main()
{
int *num;
function(&num);
printf("%d",*num);
free(num);
return(0);
}
or
int* function(void)
{
int *a= malloc(sizeof(int));
*a=10;
return a;
}
int main()
{
int *num;
num = function();
printf("%d",*num);
free(num);
return(0);
}
malloc()ed memory is only freed when you call free() on it. It can be accessed by anybody with a valid pointer to it until that time.
No. You are passing the pointer numby value, hence the changes made by the function will not be reflected in main. So effectively there is no way to access/free the allocated memory from main
To fix this you can pass the address of num or return a from function and collect the returned value in num
Memory is not freed. Any function can allocate memory and any other can deallocate it. It's a real mess if you're not super-finicky, until... someone invented the Garbage Collection.
malloc is working fine (though you will have to call free() on the pointer it returns). The problem here is that you aren't returning a pointer to the memory it allocated.
"int * a", your parameter to function() is the address of an integer. The usual way to return that would be to rewrite your function as follows:
int * function()
{
int * a = (int *)malloc(sizeof(int));
*a = 10;
return a;
}
To return it via a parameter, you need to return the address of the pointer:
// pp points to a pointer
void function( int ** pp )
{
// Assign allocated memory to the thing that pp points to
*pp = (int *)malloc( sizeof( int ) );
// Get the thing pp points to -- a pointer.
// Then get the thing which THAT pointer points to -- an integer
// Assign 10 to that integer.
**pp = 10;
}
void main()
{
int * p = NULL;
function( & p );
printf( "%d\n", *p );
free( p );
}
And now you know why they invented C#.
Here's a way to rewrite your allocation thing so it's more clear:
void function( int ** pp )
{
int * newmemory = (int *)malloc( sizeof( int ) );
// Assign 10 to the integer-sized piece of memory we just allocated.
*newmemory = 10;
// Assign allocated memory to the thing that pp points to.
*pp = newmemory;
}
You can store the direct address of the allocated memory in a list container then create a function to loop, access each address into a free function, and then pop out the address. You can insert the address directly into the free function like free(myaddresslist.front()); myaddresslist.pop_front(); . This is a quasi way of doing your own garbage collection without having to change your entire project to GC based languages. Use myaddresslist.size() to make sure you don't call free() on an empty field (resulting in a crash) and to determine the number of loops to take.

Resources