Here is a function(returnArr) to read 10 integers and store them in an array. increment each by 2, and return the array base address. Using the base address, the array elements are printed (in three()).
#include<stdio.h>
#include<stdlib.h>
int* returnArr()
{
int arr[10];
size_t iter = 0;
while( iter < 10 )
{
scanf("%i",arr+iter);
arr[iter]+=2;
printf("%i ",arr[iter]);
iter+=1;
}
return arr;
}
void three()
{
size_t iter = 0;
int* arr = returnArr();
//putchar('\n');
while( iter < 10 )
{
printf("%i ",arr[iter]);
iter+=1;
}
return;
}
int main()
{
//one();
//two();
three();
return 0;
}
Ideally the program should print garbage values since the address points to the location of a local variable in another function which was called before the array traversal.
But it is actually printing the array elements when the putchar function call is commented, garbage values when the getchar function call is included in the program code.
Using gcc 4.7.2 on Debian.
Can anyone explain this ?
-Newbie
Your program has undefined behavior: you cannot return an array that has been allocated locally:
int* returnArr()
{
int arr[10];
...
return arr; // <<== This is undefined behavior
}
The results that you see after the call of returnArr are, well, undefined: the memory returned from the function is up for grabs, so it gets altered by arbitrary events, such as making an addition function call.
But it is actually printing the array elements when the putchar function call is commented, garbage values when the getchar function call is included in the program code.
Without the call of putchar the memory of arr stays undisturbed, so you get old values. When you call putchar, its return address is placed on the stack, right at the spot where arr is stored. This is a general problem with undefined behavior - you do not get a "fail fast" behavior, or even a guaranteed failure with it. This answer provides a very nice analogy to what's happening when you return a pointer to local from a function.
To fix this problem, allocate the array dynamically, and free it in the caller, like this:
int *arr = malloc(10*sizeof(int)); // Instead of int arr[10];
...
int* arr = returnArr(); // Call the function
... // Use arr here, then...
free(arr); // free it when you are done.
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.
This question already has answers here:
Returning an array from a function in C: Segmentation Fault [duplicate]
(3 answers)
How to access a local variable from a different function using pointers?
(10 answers)
Closed 4 years ago.
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#define len 10
int *randomArray(void);
int main()
{
srand(time(NULL));
int *rArray = (int *)malloc(sizeof(int) * len);
rArray = randomArray();
for (int i = 0; i < len; i++) {
printf("%d ", *(rArray+i));
}
puts("");
free(rArray);
}
int *randomArray(void)
{
int array[len] = { 0 };
for (int i = 0; i < len; i++) {
array[i] = rand() % len;
}
return array;
}
Task is to create an array of ints and have a function fill that array with random numbers. The function randomArray() works just fine, but for some reason the assignment rArray = randomArray() doesn't work correctly, although some elements of rArray are valid numbers not gibberish. Also, the last main line free(rArray); crashes the program which is just mind numbing for me, it doesn't make any sense. If I remove the line the program doesn't crash but we all know you need to free() a malloc()-ed array.
The primary problem here is, array is a local variable in the randomArray() function scope. Once the function returns, the returned address becomes invalid. Any further attempt to use the memory will lead to undefined behavior.
Moreover, from your approach, you are trying to overwrite the allocated memory by the address being returned from the function call, which will cause memory leak. Rather, change your design, pass the allocated memory to the function as the argument and just fill the elements using the rand() call.
The randomArray return a pointer to the first element of the local array array.
That pointer becomes invalid immediately once the function returns as the variable goes out of scope. Using it in any way will lead to undefined behavior.
What makes it even worse is that you reassign the pointer rArray, making you lose the original memory you allocated. That means your call to free again will lead to UB.
To solve both problems, pass the pointer and the size as arguments to the randomArray function:
void randomArray(int *array, int size)
{
for (int i = 0; i < size; ++i)
{
array[i] = rand() % size;
}
}
int *randomArray(void)
{
int array[len] = { 0 };
//...
return array;
}
array goes out of scope at } and accessing this returned pointer is UB.
Moreover rArray = randomArray(); leaks memory since now you cannot free the malloc'd memory. You should pass the rArray to a function, which will be responsible for filing it.
In randomArray() function, you are returning the array that is allocated on stack. That array will be freed when returning from randomArray() function. Instead, you can do this:
void randomArray(int * array)
{
// Remove this int array[len] = { 0 };
for (int i = 0; i < len; i++) {
array[i] = rand() % len;
}
// Remove this .. return array;
}
And call randomArray(rArray) from main()
Save pointer to array in struct.
I would like to store the pointer to array of int into struct but I am having trouble.
Below my code with commentaries:
typedef struct _index {
int *data;
} Index;
void adder(struct _index *s){
int i;
int arr[maxint];
for(i=0; i<maxint; i++) {
arr[i] = i+42;
}
//i got a gibberish
//s->data = arr;
//works fine
s->data = (int *) malloc(maxint * sizeof(int));
s->data = memcpy(s->data, arr, maxint * sizeof(int));
)
int main() {
Index n;
int i;
//this method also works.
//int arr[maxint];
//for(i=0; i<maxint; i++) {
// arr[i] = i+42;
//
//}
//n.data = arr;
adder(&n);
for(i=0; i<maxint;i++) {
printf("%d-", n.data[i]);
}//testing
return 0;
}
when i make assignment, i got strange numbers:
117-118-119-120-12-0-22-2292964-0-2293008-127-0-129-130-131-0-0-0-0-0-0-138-0
but if i use malloc and memcpy all works fine
You got gibberish in your first case, because you tried to "return" the address of a local variable from a function through the pointer. Once the function finishes execution, the int arr[maxint]; won't be valid. In other words, after adder() finishes execution, int arr[maxint]; goes out of scope and it's lifetime is over. So, the (returned) pointer becomes invalid and using that further in the caller function will result in undefined behaviour.
Solution:
As you've done correctly, using dynamic memory.
use static variable (not a good approach, but possible).
In both the aforesaid approach, the lifetime of the variable ( static arr array/ malloc()ed memory) is not limited to function scope and thus, the pointer to the meory will be vaild in the caller function.
The array arr in the adder() function is on the stack and only exists as long as the code in that function is running. Once adder() returns that memory is re-used by the rest of the program and its content overwritten.
int arr[] is placed on the stack and gets removed from the stack when it goes out of scope. So you will point to garbage.
It works fine if you include it in your main because that way it hasn't gone out of scope yet.
Malloc works because you allocate memory and not just place it on the stack.
I want to use only studio.h library to convert from decimal number to binary number by using an array to store remainder but the result is not correct, maybe i have problem with memory allocation or return value is wrong, please help me to check it.
Thank you so much!
#include <stdio.h>
int n = 0;
int* DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
void main(){
int *d1 = DecimalToBinary(5);
int *d2 = DecimalToBinary(10);
for(int i = n-1 ;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
for(int i = n-1 ;i>=0;i--)
printf(" %d",d2[i]);
}
You return a pointer to a local array. That local array is on the stack, and when the function returns the array goes out of scope and that stack memory will be reused when you call the next function. This means that the pointer will now point to some other data, and not the original array.
There are two solutions to this:
Declare the array in the function calling DecimalToBinary and pass it as an argument.
Create the array dynamically on the heap (e.g. with malloc) and return that pointer.
The problem with method 2 is that it might create a memory leak if you don't free the returned pointer.
As noted by Craig there is a third solution, to make the array static inside the function. However in this case it brings other and bigger problems than the two solutions I originally listed, and that's why I didn't list it.
There is also another serious problem with the code, as noted by Uchia Itachi, and that is that the array is indexed by a global variable. If the DecimalToBinary function is called with a too big number, or to many times, this global index variable will be to big for the array and will be out of bounds for the array.
Both the problem with dereferencing a pointer to an out-of-scope array and the indexing out of bounds leads to undefined behavior. Undefined behavior will, if you're lucky, just lead to the wrong result being printed. If you're unlucky it will cause the program to crash.
You are returning a pointer to a locally allocated array. It is allocated on the stack, and goes away when the function returns, leaving your pointer pointing to garbage.
You have a few options. You could pass an array in to fill:
void DecimalToBinary(int result[10],int number){
while(number!=0){
result[n++] = number%2;
number/=2;
}
return result;
}
// usage example:
int b[10];
DecimalToBinary(b, 42);
Or you could allocate an array on the heap:
int* DecimalToBinary(int number){
int *a = (int *)malloc(sizeof(int) * 10);
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
// usage example
int *b = DecimalToBinary(42);
free(b); // when finished with it
Or you could wrap the array in a struct:
typedef struct {
int b[10];
} result;
result DecimalToBinary(int number){
result r;
while(number!=0){
r.b[n++] = number%2;
number/=2;
}
return r;
}
// usage example
result r = DecimalToBinary(42);
If you do the malloc() option, do not forget to free() the returned data when you're done with it, otherwise it will hang around. This is called a memory leak. In more complex programs, it can lead to serious issues.
Note: By the way, if your number is larger than 1023 (10 binary digits), you'll overrun the array. You may also wish to explicitly stop once you've stored 10 digits, or pass the size of the array in, or compute the required size first and allocate that much space. Also, you will get some odd results if your number is negative, you might want to use number&1 instead of number%2.
Note 2: As noted elsewhere, you should make n local, or at the very least reinitalize it to 0 each time the function is called, otherwise it will just accumulate and eventually you'll go past the end of the array.
int[10] is not the same as int *; not only is the former created on the stack, it is a different type alltogether. You need to create an actual int * like so:
int *a = malloc (10 * sizeof (int));
Of course, don't forget to free() it after use!
What you can also do and what is commonly done in C is creating the array where it is called and provide a pointer to that array to the function, this way when the array is on the stack of the function that calls it and not in the function self. We also have to specify the size of the array on to that function, since the function cannot know to how many elements the pointer points to
void DecimalToBinary( int number, int* output, unsigned size ) {
/*adapt this to your liking*/
int i;
for ( i = 0; i < size && number != 0; i++) {
output[i] = number%2;
number/2;
}
}
and in you main function you would call it like this:
int array[10];
DecimalToBinary( 5, array, sizeof(array)/sizeof(array[0]));
now array has the same result as a would have had in your example.
The problem in your code lies here..
int * DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
The array a scope is only till this function. Once this function terminates, the memory allocated for this array will be released, either u need to use dynamic memory allocation or make array a global.
This is the correct program:
#include <stdio.h>
int n = 0;
int a[10] = {0};
int* DecimalToBinary(int number){
n = 0;
while(number!=0){
a[n++] = number%2;
number = number/2;
}
return a;
}
int main(){
int *d1;
int *d2;
int i;
d1 = DecimalToBinary(5);
for(i = n-1;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
d2 = DecimalToBinary(10);
for(i = n-1;i>=0;i--)
printf(" %d",d2[i]);
printf("\n");
}
I have a function that I pass an array into and an int into from my main function. I am doing operations to the array inside this new function, let's call it foo. In foo, I initialize another array with 52 cells all with 0. I do operations on the array that I passed from main, and transfer that data to the newly initialized array. I want to return the new array back to the main function. But of course, I can't return data structures like arrays. So I instead return an int pointer that points to this array. Inside the int main, I pass the pointer to have it point to various cells in the array. When I print the results of what the pointer is pointing to, it should either be pointing to 0 or an integer greater than 0. But instead, I get inconsistent results. For some reason, some of the values that SHOULD be 0, prints out garbage data. I've been trying to spot the bug for some time, but I just wanted a second hand look at it. Here is just the GENERAL idea for the code for this portion anyways...
int main(){
int *retPtr;
char input[] = "abaecedg";
retPtr = foo(input, size);
for(i=0; i<52; i++){
// error displayed here
printf("%d\n", *(retPr + i));
}
}
int foo(char input[], int size)
{
int arr[52] = {0}; // should initialize all 52 cells with 0.
int i=0, value; // looking for non-zero results in the end.
int *ptr = &arr[0];
for(i=0; i<size; i++){
if(arr[i] > 64 && arr[i] < 91){
value = input[i] - 65;
arr[value]++;
}
}
return ptr;
}
Hopefully this makes sense of what I'm trying to do. In the foo function, I am trying to find the frequency of certain alphabets. I know this might be a bit cryptic, but the code is quite long with comments and everything so I wanted to make it as succinct as possible. Is there any possible reason why I'm getting correct values for some (numbers > 0, 0) and garbage values in the other?
The reason you get garbage back is that the array created in foo is allocated in foos stack frame, and you then return a pointer into that frame. That frame is discarded when foo returns.
You should allocate the array on the heap (using malloc and friends) if you want it to remain after foo returns. Don't forget to free() it when you're done with the array.
int main(){
char input[] = "abaecedg";
int retPtr[] = foo(input, size); //An array and a pointer is the same thing
...
free(retPtr);
}
int *foo(char input[], int size)
{
int arr[] = calloc(52*sizeof(int); // should initialize all 52 cells with 0.
...
arr[value]++;
...
return arr;
}
Another way is to let foo take an array as a parameter and work with that, in this way:
int main(){
int ret[52] = {0};
...
foo(input, size, ret);
...
}
void foo(char input[], int size, int *arr)
{
...
arr[value]++;
...
return; //Don't return anything, you have changed the array in-place
}
The reason this works is because an array is the exact same thing as a pointer, so you are really passing the array by reference into foo. arr will be pointing to the same place as ret, into the stack frame of main.
In function foo the array arr is a local array, that is, allocated on the stack. You must not return any pointer of data allocated on the stack, since the stack is rewinded after you return from the function, and its content is no more guaratneed.
If you want to return an array you should allocate it on the heap using malloc, for example, and return the pointer malloc returned. But you will then have to free that memory somewhere in your program. If you fail to free it you will have what's called a "memory leak", which may or may not crash/disturb this program from running again, depending on your environment. A not clean situation, that's for sure.
That's why I consider C not so good for functional programing idioms, such as returning things from function (unless they are primitive types). I would achieve what you tried to do by passing another array to foo - an output array, companioned by a size variable, and fill that array.
Alternately, you could wrap the array within a struct and return that struct. Structs can be returned by value, in which case they are copied via the stack to the caller function's returned value.