Why local variable defined in function 'getAr' is accessible in main? - c

int *getAr()
{
int *a;
int i;
a=(int*)malloc(sizeof(int)*10);
for(i=0;i<10;i++)
a[i]=i;
return(a);
}
int main()
{
int *a;
int i;
a=getAr();
for(i=0;i<10;i++)
printf("%d\t",a[i]);
printf("\n");
return 0;
}
OUTPUT is:
0 1 2 3 4 5 6 7 8 9

When you malloc(), the memory is taken from the heap. Which is not unloaded when the function returns (unlike the stack).

Others have already pointed out the reason, adding a few more points to help.
Local/Automatic variables have their scope inside the function call, and not in any other function.
But here, you are returning the pointer to dynamically allocated memory, which won't be freed up after the function call, and this is the reason why the program works fine, in spite of the fact that there is a memory leak.
You will have to explicitly call free() to free up the memory you allocated using malloc().
I think you are confused in this case:
// When the array is on the stack:
int *getAr() {
int b[10]; // 'b' allocated on stack
int *a = b; // 'a' allocated on stack
return (a); // or return (b);
}
void main () {
int * a = getAr();
printf("%d \n", a[0]); // this may not give you the correct result
}
A good tutorial on stack and heap will help you:
http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html

Its value is accessible inside main function because it is heap-allocated. Heap allocated data is accessible to any function in your program, opposed by stack-allocated data, which is accessible only to the function that created it due to stack unloading.
Source: http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html#sec-3

Returning pointer to automatic local variable is not allowed in C as it does not exist once function returns.
Otherwise returning pointer to static local variable and variables that allocated dynamically is allowed.

Related

How to declare a Global variable inside any function in 'C'?

I want to declare a global variable inside a main() function...
Below is what I want the program to act like
#include<stdio.h>
int a[6];
int main()
{
int n;
scanf("%d",&n);
}
I want to create an array of user given size (here n-size) and I want to access that array globally.
So instead of creating array of size '6' outside the main() function, I want to create array of 'n' size globally instead of passing array whenever function is called...
You can declare a pointer as global variable and assign buffer to that in main().
#include<stdio.h>
#include<stdlib.h>
int *a;
int main()
{
int n;
scanf("%d",&n);
a = calloc(n, sizeof(*a)); /* calloc() initializes the allocated buffer to zero */
if (a == NULL)
{
/* calloc() failed, handle error (print error message, exit program, etc.) */
}
}
You may want to use an array allocated into the heap by using malloc
#include<stdio.h>
int *a;
int main()
{
int n;
scanf("%d", &n);
a = malloc(sizeof(*a) * n);
if(a == NULL) {
// malloc error
}
// use your array here
free(a); // at the end of the program make sure to release the memory allocated before
}
You cannot do that.
The closest you can get it, define a pointer in file scope (i.e., global), allocate memory to it by using allocator function (malloc() and family) and use the same pointer in other function calls as necessary. As the lifetime of the allocated memory is until deallocated programmatically (passed to free()), other functions can make use of the allocated memory.

Memory allocation using for loop

My Doubt is regarding only memory allocation so don't think about program output
#include<stdio.h>
int main(){
for(int i=0;i<20;i++){
char *str=malloc(sizeof(char)*6); //assuming length of each string is 6
scanf("%s",str);
insertinlinkedlist(str);
}
}
whenever i allocate memory here as shown above only the base address of char array will pass to linked list,and that is the memory block allocated for char array is inside main only and i am storing the base address of that array in str which is local to main and is passed to insetinlinkedlist
I want to ask whenever memory is allocated inside loop than why the number of
memory blocks(no of char arrays declared ) are created equal to n (number of time loop runs) since variable name is same we should be directed to same memory location
Note I have checked in compiler by running the loop all the times when loop runs memory the value of str is different
is The above method is correct of allocating memory through loop and through same variable "Is the method ensures that every time we allocate memory in above manner their will be no conflicts while memory allocation and every time we will get the address of unique memory block"
Now above doubt also creates a doubt in my mind
That if we do something like that
int main(){
for(int i=0;i<n;i++){
array[50];
}
}
then it will also create 50 array inside stack frame
malloc returns a pointer to the first allocated byte. Internally it keeps track of how much memory was allocated so it knows how much to free (you do need to insert calls to free() or you'll leak memory, by the way). Usually, it does this by allocating a little bit of memory before the pointer it gives you and storing the length there, however it isn't required to do it that way.
The memory allocated by malloc is not tied to main in any way. Currently main is the only function whose local variables have a pointer to that memory, but you could pass the pointer to another function, and that function would also be able to access the memory. Additionally, when the function that called malloc returns, that memory will remain allocated unless manually freed.
The variable name doesn't matter. A pointer is (to first approximation) just a number. Much like how running int a = 42; a = 20; is permitted and replaces the previous value of a with a new one, int *p = malloc(n); p = malloc(n); will first assign the pointer returned by the first malloc call to p, then will replace it with the return value of the second call. You can also have multiple pointers that point to the same address:
int *a = malloc(42);
int *b = malloc(42);
int *c = a;
a = malloc(42);
At the end of that code, c will be set to the value returned by the first malloc call, and a will have the value returned by the last malloc call. Just like if you'd done:
//assume here that f() returns a different value each time
//it's called, like malloc does
int a = f();
int b = f();
int c = a;
a = f();
As for the second part of your question:
for(int i=0;i<n;i++){
int array[50];
}
The above code will create an array with enough space for 50 ints inside the current stack frame. It will be local to the block within the for loop, and won't persist between iterations, so it won't create n separate copies of the array. Since arrays declared this way are part of the local stack frame, you don't need to manually free them; they will cease to exist when you exit that block. But you could pass a pointer to that array to another function, and it would be valid as long as you haven't exited the block. So the following code...
int sum(int *arr, size_t n) {
int count = 0;
for (size_t i = 0; i < n; i++) {
count += arr[i];
}
return count;
}
for(int i=0;i<n;i++){
int array[50];
printf("%d\n", sum(array, 50));
}
...would be legal (from a memory-management perspective, anyway; you never initialize the array, so the result of the sum call is not defined).
As a minor side note, sizeof(char) is defined to be 1. You can just say malloc(6) in this case. sizeof is necessary when allocating an array of a larger type.

accessing variable length array after its memory should have been deallocated

I'm currently studying variable length array and automatic storage.
I have the following code that allocate memory for an variable length array myArray inside function vla, and return a pointer to the variable length array from the function.
#include <stdio.h>
int * vla(int n){
int myArray[n];
myArray[0] = 10;
myArray[1] = 11;
int * pointerToInt = myArray;
return pointerToInt;
}
int main(void){
int * pointerToInt = vla(10);
printf("%d, %d", pointerToInt[0], pointerToInt[1]); // prints 10, 11
return 0;
}
I thought that variable length array belong to the automatic storage class (i.e. the memory for the variable length array will be allocated when we enter the function containing the variable length array, and the memory is automatically deallocated after the function exit)
So according to this logic, the memory allocated to myArray variable length array is deallocated after we return from vla method, but how come I can still correctly access the first and second element of the variable length array?
Is this behavior defined? or it is undefined behaviour that just happen to work?
myArray is a stack/auto variable created on the stack memory. Remember memory always exists. It is just owned by different pointers based on allocation and deallocation. The reason why you can still access same values is that the same piece of memory has not been assigned to another pointer and not been overwritten.
To evaluate it. Create another function that allocates same amount from stack but puts different values. Or add arguments in the same function and call it twice with different values. You will then see the difference.
#include <stdio.h>
int * vla(int n, int a, int b){
int myArray[n];
myArray[0] = a;
myArray[1] = b;
int * pointerToInt = myArray;
return pointerToInt;
}
int main(void){
int * pointerToInt = vla(10, 10, 11);
vla(10, 20, 21); // over write stack
printf("%d, %d", pointerToInt[0], pointerToInt[1]); // prints 20, 21
return 0;
}
By the way returning stack memory from vla is not a good idea. Dynamic memory is allocated from heap using malloc family of functions.
You can still correctly access the first and second element of the variable length array because you are assigning base address of the myArray to pointerToInt. Auto variables have a life inside the block only, but in this program we are using pointer to access the data in the memory, as long as that part of stack is not allocated to any other program, we can access that part of stack. If that part of stack is allocated to some other process we will get segmentation fault as we are trying to access unauthorized memory

Returning an array from a function in C: Segmentation Fault [duplicate]

This question already has answers here:
How is the array stored in memory?
(4 answers)
How to access a local variable from a different function using pointers?
(10 answers)
Closed 6 years ago.
I am trying to implement a simple program using a header file where a function in the header file accepts an int array and returns an int array too.
In header.h:
int* point(int a[]);
In header.c:
#include<stdio.h>
#include "header.h"
int* point(int a[])
{
printf("In the point function\n");
int array[4],i;
for(int i=0;i<4;i++)
{
printf("%dth Iteration\n",i);
array[i]=a[i];
}
return array;
}
In test.c:
#include<stdio.h>
#include "header.h"
void main()
{
int *array,i;
int a[]={1,2,3,4};
printf("calling point function\n");
array=point(a);
printf("Back in the main function\n");
for(i=0;i<4;i++)
{
//SEGMENTATION FAULT HERE
printf("%d\n",array[i]);
}
}
I am getting a segmentation fault at the print loop in test.c.
You cannot return arrays from functions. When point() returns, the local array within this function goes out of scope. This array is created on the stack, and will get destroyed once the function finishes returning. All memory associated with it is discarded, and the returned pointer points to a position on the stack that doesn't exist anymore. You need to instead allocate a pointer on the heap, and return that instead. This allows array to be shared across your program.
Instead of:
int array[4];
you need to dynamically allocate a pointer using malloc():
int *array = malloc(4 * sizeof(*array)); /* or sizeof(int) */
if (array == NULL) {
/* handle exit */
}
malloc() allocates requested memory on the heap, and returns a void* pointer to it.
Note: malloc() can return NULL when unsuccessful, so it needs to be checked always. You also need to free() any memory previously allocated by malloc(). You also don't need to cast return of malloc().
Another thing to point out is using the magic number 4 all over your program. This should really be calculated using sizeof(a)/sizeof(a[0]).
You can declare this as a size_t variable in your main():
size_t n = sizeof(a)/sizeof(a[0]);
Or you can use a macro:
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
And simply call ARRAYSIZE(a) everytime you want the size of the array.
The issue has to do with the scope of the array variable that you're returning in your method. Right now you're returning array, a local variable defined in the method, point. However, once point is finished executing, all local variables within the function frame, including array will be discarded from main memory. So even though you still get a memory address from point, there's no telling what could be at that memory address. Therefore, treating array as an int array when printing out its elements will lead to a segmentation fault.
My suggestion to fix this is to allocate memory from the heap using malloc so that array lasts outside the frame of point. The solution should look like this,
int* point(int a[])
{
printf("In the point function\n");
int *array = (int *) malloc(4 * sizeof(int)); //dynamically allocate memory for 4 integers
int i;
for(i=0;i<4;i++)
{
printf("%dth Iteration\n",i);
array[i]=a[i];
}
return array;
}
You could either define array[] as a global variable, or dynamically allocate memory for it as mentioned in the above comments using malloc().
Since array[] is allocated in the function point(), it gets deleted once the function exits. Hence, a reference to the returned pointer causes a segmentation fault.

Returning array address from function [duplicate]

This question already has answers here:
Returning Arrays/Pointers from a function
(7 answers)
Closed 8 years ago.
I was trying to pass the array address from the function to the main function that's happening perfectly. But when I dereference the address in main(), I am getting junk values. I am guessing that the variables in the array_address memory lives only within the scope of the function. If this is the case, how do you return an array generated within a function to another function?
Here's my code:
int* letssee(int something)
{
int* array_address;
int a[10], i=0;
array_address = &a[0];
for (i; i<something;i++)
{
*(array_address+i) = i;
printf("\n%p, %d",(array_address+i), *(array_address+i));
}
return array_address;
}
int main()
{
int i= 5,j;
int* catch_address;
catch_address = letssee(i);
printf("\n");
for (j= 0; j<i; j++)
{
printf("%p, %d\n", (catch_address+j),*(catch_address+j));
}
return 0;
}
you can't return an array defined in a function as it is allocated on the stack and will disappear after the function has finished. Instead you allocate memory
int *array_address = malloc(sizeof(int) * 10);
however, you have to manage the memory, meaning you have to "free" it when you are finished with it, otherwise you will leak memory
The other approach is to pass the memory preallocated into a function (whether it be via malloc or the stack or global)
int* letsee(int something, int* array_address, int count);
if you simply make the array static, you are effectively making a global variable, multiple calls to the function will return the SAME address and may cause strange behaviour if you are expecting new arrays for each call.

Resources