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()
Related
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
I have written the following code:
#include <stdio.h>
#include <stdlib.h>
typedef struct _NeuralNetwork{
int input_rows;
int input_columns;
double **inputs;
}NeuralNetwork;
void main(){
// structure variable
NeuralNetwork *nn;
int count;
int i,j;
nn->input_rows = 2;
nn->input_columns = 3;
// create the array of double pointers using # of rows
nn->inputs = (double **)malloc(nn->input_rows * sizeof(double *));
// each pointer gets an array of double values
for (i=0; i<nn->input_rows; i++){
nn->inputs[i] = (double *)malloc(nn->input_columns * sizeof(double));
}
// assign values
count = 0;
for (i = 0; i < nn->input_rows ; i++)
for (j = 0; j < nn->input_columns; j++)
nn->inputs[i][j] = ++count;
// print those values
for (i = 0; i<nn->input_rows; i++)
for (j = 0; j < nn->input_columns; j++)
printf("%f ", nn->inputs[i][j]);
/* Code for further processing and free the
dynamically allocated memory*/
return;
}
When I compile this everything is okay. But after running it, I get a segmentation fault error:
Segmentation fault (core dumped)
I am not sure, where the mistake is. Can somebody help?
Note: When I use nn as structure variable instead of a structure, then everything is fine. But I want to use it as structure pointer and access the structure members via "->" and not via "." since I plan to pass nn as pointer to another function later.
Thank you in advance :)
The variable nn is a pointer, but that pointer is never initialized. You subsequently read and dereference that pointer using an operation such as nn->input_rows = 2;. This invokes undefined behavior.
In this particular case, nn likely contains some garbage value. By dereferencing that pointer value, you are attempting to read from memory you probably aren't allowed to. This is what causes the crash.
By defining nn as an instance of a struct instead of a pointer, as you said you tried, you avoid this issue. You can still however pass a pointer to other functions by taking the address of this variable and passing that to the function, i.e.:
NeuralNetwork nn;
...
myfunction(&nn)
First, do not use void main(), it's non-standard and would eventually cause problems. The right way is int main() or int main(int argc, char** argv). Remember to return a proper value at the end of the main function, possibly 0. Consult the reference here: main function
Second, if you use NeuralNetwork *nn; you must allocate some space for it in memory. It's a pointer to some memory address, if you don't allocate it who knows where it points. That's why you're getting the segfault. You must allocate memory for it in the following way:
NeuralNetwork *nn = malloc(sizeof(NeuralNetwork));
Then it should work properly.
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.
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.
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.
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");
}