Can someone tell me, if function fun() is correct?
#include <stdio.h>
#include <stdlib.h>
int *fun(int *, int *, int, int);
int main(void) {
int v1[] = {1,2,3,4,5};
int v2[] = {6,7,8,9,10};
int v1Size = sizeof(v1)/sizeof(v1[0]);
int v2Size = sizeof(v2)/sizeof(v2[0]);
int *v = fun(v1, v2, v1Size, v2Size);
if(v == NULL)
exit(EXIT_FAILURE);
for(size_t i = 0; i < v1Size; ++i)
printf("%d ", v[i]);
}
int *fun(int *v1, int *v2, int v1Size, int v2Size){
if(v1Size!=v2Size)
return NULL;
const int size = v1Size;
int v[size];
for(int i=0; i<size; i++)
v[i]=v1[i]+v2[i];
int *p = v;
return p;
}
For me, it returns the pointer that points memory that will be freed after leaving the fuction body. But valgrind doesn't show any error and it works just fine.
works just fine
Stop !! it's one of the possible outcome of invoking undefined behavior.
As you correctly mentioned, the returned pointer won't be valid (VLAs reside in auto scope (stack), in general, as in gcc) after returning from fun(). Using the return value will lead to UB.
Returning the address of a local variable is not "fine". Once the function exits, v no longer exists, so any pointer to it is no longer valid. Obviously, the storage that v occupied still exists, and as long as nothing else overwrites that storage, your code will appear to function correctly.
Note the emphasis on appear. Your code could just as easily crash, or give garbled output, or otherwise be put into a bad state. It depends on how you use that returned pointer value.
v has auto storage duration, meaning storage for it is allocated at function entry and released at function exit. Valgrind isn't going to say boo about it, because it's not the kind of thing Valgrind checks.
Related
This question is meant to be used as a canonical duplicate for this FAQ:
I am allocating data dynamically inside a function and everything works well, but only inside the function where the allocation takes place. When I attempt to use the same data outside the function, I get crashes or other unexpected program behavior.
Here is a MCVE:
#include <stdlib.h>
#include <stdio.h>
void create_array (int* data, int size)
{
data = malloc(sizeof(*data) * size);
for(int i=0; i<size; i++)
{
data[i] = i;
}
print_array(data, size);
}
void print_array (int* data, int size)
{
for(int i=0; i<size; i++)
{
printf("%d ", data[i]);
}
printf("\n");
}
int main (void)
{
int* data;
const int size = 5;
create_array(data, size);
print_array(data, size); // crash here
free(data);
}
Whenever print_array is called from inside the create_array function, I get the expected output 0 1 2 3 4, but when I call it from main, I get a program crash.
What is the reason for this?
The reason for this bug is that the data used by the create_array function is a local variable that only exists inside that function. The assigned memory address obtained from malloc is only stored in this local variable and never returned to the caller.
Consider this simple example:
void func (int x)
{
x = 1;
printf("%d", x);
}
...
int a;
func(a);
printf("%d", a); // bad, undefined behavior - the program might crash or print garbage
Here, a copy of the variable a is stored locally inside the function, as the parameter x. This is known as pass-by-value.
When x is modified, only that local variable gets changed. The variable a in the caller remains unchanged, and since a is not initialized, it will contain "garbage" and cannot be reliably used.
Pointers are no exception to this pass-by-value rule. In your example, the pointer variable data is passed by value to the function. The data pointer inside the function is a local copy and the assigned address from malloc is never passed back to the caller.
So the pointer variable in the caller remains uninitialized and therefore the program crashes. In addition, the create_array function has also created a memory leak, since after that function execution, there is no longer any pointer in the program keeping track of that chunk of allocated memory.
There are two ways you can modify the function to work as expected. Either by returning a copy of the local variable back to the caller:
int* create_array (int size)
{
int* data = malloc(sizeof(*data) * size);
for(int i=0; i<size; i++)
{
data[i] = i;
}
print_array(data, size);
return data;
}
int main (void)
{
int* data;
const int size = 5;
data = create_array(size);
print_array(data, size);
}
or by passing the address to the caller's pointer variable and write directly to the caller variable:
void create_array (int** data, int size)
{
int* tmp = malloc(sizeof(*tmp) * size);
for(int i=0; i<size; i++)
{
tmp[i] = i;
}
*data = tmp;
print_array(*data, size);
}
int main (void)
{
int* data;
const int size = 5;
create_array(&data, size);
print_array(data, size);
}
Either form is fine.
I want to make a function that returns an int array. However I am having difficulties as this attempt will return the same value for both out1 and out2
int * foo(int bar) {
static int fizz[2] = {0, 0};
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz;
}
int main() {
int *out1 = foo(1);
int *out2 = foo(2);
printf("(%d, %d)\n(%d, %d)", out1[0], out1[1], out2[0], out2[1]);
}
Output:
(2, 3)
(2, 3)
And then this solution does not compile as I am returning the address of a local variable (which is what lead me to attempt the static keyword in the first place.
int * foo(int bar) {
int fizz[2] = malloc(2*sizeof(int));
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz;
}
int main() {
int *out1 = foo(1);
int *out2 = foo(2);
printf("(%d, %d)\n(%d, %d)", out1[0], out1[1], out2[0], out2[1]);
}
So I know why this code is not working but I have no clue what other methods I could attempt to successfully write this function.
Your second attempt is close, and certainly along the right path. However, the return value from the malloc function is a pointer (not an array) and the fizz variable should be declared as such (a pointer-to-integer, or int*).
Your concern about this "returning the address of a local variable" is not relevant, in this case; what you are returning is the value of a local variable, which just happens to be an address. The value of that address, returned by malloc, will be copied to the value returned by the function.
Also, when using malloc , never forget to release the memory when you're finished with it, using the free function.
Here's a working code sample, which is changed very little from your second snippet:
#include <stdio.h>
#include <stdlib.h>
int* foo(int bar)
{
int *fizz = malloc(2 * sizeof(int)); // Save the allocated pointer (locally)...
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz; // ... and return a COPY of the value of that address!
}
int main()
{
int* out1 = foo(1);
int* out2 = foo(2);
printf("(%d, %d)\n(%d, %d)", out1[0], out1[1], out2[0], out2[1]);
// Don't forget to free the allocated memory...
free(out1);
free(out2);
}
It's not entirely clear whether or not you understand why your first snippet gives the same values for both out1 and out2. So, just in case: the static int fizz[2] line declares a fixed block of memory – though it's only accessible, by name, from within that function. Each call to foo will return a pointer to that (same) memory, and the printf call will display the values assigned to its elements in the most recent (latest) update.
Your first code is also fine, only when to print the result....
int* foo(int bar) {
static int fizz[2]={0,0};
fizz[0] = bar;
fizz[1] = bar + 1;
return fizz;
}
int main() {
int* out1=foo(1);
printf("%d,%d\n", out1[0], out1[1]);
int* out2=foo(2);
printf("%d,%d \n", out2[0], out2[1]);
return 0 ;
}
gives the result :
1,2
2,3
when trying to print the values of struct variables after the function returns it prints some random text (which I think is due to memory allocation error)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char s1[20];
char s2[20];
int n1;
} TEST;
void allocate(TEST *T, int n){
T = malloc(sizeof(TEST)*n);
for(int i=0; i<n; i++){
sprintf((T+i)->s1, "string 1 of %d", i);
sprintf((T+i)->s2, "string 2 of %d", i);
(T+i)->n1 = i;
}
}
int main(){
TEST *T;
int n = 3;
allocate(T, n);
for(int i=0; i<n; i++){
printf("%s\n%s\n%d\n\n", (T+i)->s1, (T+i)->s2, (T+i)->n1);
}
}
No, C absolutely does not call free automatically for you.
The issue in your program is that T in the caller to allocate is not changed. C is strictly a pass by value language.
One solution is to change the type of T to TEST** in allocate:
void allocate(TEST **T, int n){
with
allocate(&T, n);
in main. You then call free in main.
The program causes undefined behaviour by passing uninitialized T to the function. Furthermore you never return the new pointer value from the function back to main.
The pointer to new memory is an output of the function, not an input. So it should be a return value, not a parameter. For example:
TEST* allocate(int n)
{
TEST* T = malloc(sizeof(TEST)*n);
// etc.
return T;
}
and then in main:
TEST* T = allocate(n);
// ... use T ...
free(T);
As said by the already given answers you need to call free to free the memory.
You want to allocate the pointed memory area, so you need a TEST**:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char s1[20];
char s2[20];
int n1;
} TEST;
void allocate(TEST **T, int n){
*T = malloc(sizeof(TEST)*n);
for(int i=0; i<n; i++){
sprintf((*T+i)->s1, "string 1 of %d", i);
sprintf((*T+i)->s2, "string 2 of %d", i);
(*T+i)->n1 = i;
}
}
int main(){
TEST *T;
int n = 3;
allocate(&T, n);
for(int i=0; i<n; i++){
printf("%s\n%s\n%d\n\n", (T+i)->s1, (T+i)->s2, (T+i)->n1);
}
free(T);
}
No. The problem with your program is that T is passed by copy to allocate, and the address to the allocated memory is assigned to this copy. To fix, you could make the first allocate parameter **T, pass in the address of T in main, and dereference the pointer to pointer in allocate and assign to it.
No, it doesn't. You need to free() malloc()ated memory yourself.
Your program, as is, leaks memory... but for this particular program it doesn't matter an awful lot since that memory is freed when the process dies.
This question is meant to be used as a canonical duplicate for this FAQ:
I am allocating data dynamically inside a function and everything works well, but only inside the function where the allocation takes place. When I attempt to use the same data outside the function, I get crashes or other unexpected program behavior.
Here is a MCVE:
#include <stdlib.h>
#include <stdio.h>
void create_array (int* data, int size)
{
data = malloc(sizeof(*data) * size);
for(int i=0; i<size; i++)
{
data[i] = i;
}
print_array(data, size);
}
void print_array (int* data, int size)
{
for(int i=0; i<size; i++)
{
printf("%d ", data[i]);
}
printf("\n");
}
int main (void)
{
int* data;
const int size = 5;
create_array(data, size);
print_array(data, size); // crash here
free(data);
}
Whenever print_array is called from inside the create_array function, I get the expected output 0 1 2 3 4, but when I call it from main, I get a program crash.
What is the reason for this?
The reason for this bug is that the data used by the create_array function is a local variable that only exists inside that function. The assigned memory address obtained from malloc is only stored in this local variable and never returned to the caller.
Consider this simple example:
void func (int x)
{
x = 1;
printf("%d", x);
}
...
int a;
func(a);
printf("%d", a); // bad, undefined behavior - the program might crash or print garbage
Here, a copy of the variable a is stored locally inside the function, as the parameter x. This is known as pass-by-value.
When x is modified, only that local variable gets changed. The variable a in the caller remains unchanged, and since a is not initialized, it will contain "garbage" and cannot be reliably used.
Pointers are no exception to this pass-by-value rule. In your example, the pointer variable data is passed by value to the function. The data pointer inside the function is a local copy and the assigned address from malloc is never passed back to the caller.
So the pointer variable in the caller remains uninitialized and therefore the program crashes. In addition, the create_array function has also created a memory leak, since after that function execution, there is no longer any pointer in the program keeping track of that chunk of allocated memory.
There are two ways you can modify the function to work as expected. Either by returning a copy of the local variable back to the caller:
int* create_array (int size)
{
int* data = malloc(sizeof(*data) * size);
for(int i=0; i<size; i++)
{
data[i] = i;
}
print_array(data, size);
return data;
}
int main (void)
{
int* data;
const int size = 5;
data = create_array(size);
print_array(data, size);
}
or by passing the address to the caller's pointer variable and write directly to the caller variable:
void create_array (int** data, int size)
{
int* tmp = malloc(sizeof(*tmp) * size);
for(int i=0; i<size; i++)
{
tmp[i] = i;
}
*data = tmp;
print_array(*data, size);
}
int main (void)
{
int* data;
const int size = 5;
create_array(&data, size);
print_array(data, size);
}
Either form is fine.
I am trying to return a pointer from a function. But I am getting a segmentation fault. Someone please tell what is wrong with the code
#include <stdio.h>
int *fun();
main()
{
int *ptr;
ptr = fun();
printf("%d", *ptr);
}
int *fun()
{
int *point;
*point = 12;
return point;
}
Allocate memory before using the pointer. If you don't allocate memory *point = 12 is undefined behavior.
int *fun()
{
int *point = malloc(sizeof *point); /* Mandatory. */
*point=12;
return point;
}
Also your printf is wrong. You need to dereference (*) the pointer.
printf("%d", *ptr);
^
Although returning a pointer to a local object is bad practice, it didn't cause the kaboom here. Here's why you got a segfault:
int *fun()
{
int *point;
*point=12; <<<<<< your program crashed here.
return point;
}
The local pointer goes out of scope, but the real issue is dereferencing a pointer that was never initialized. What is the value of point? Who knows. If the value did not map to a valid memory location, you will get a SEGFAULT. If by luck it mapped to something valid, then you just corrupted memory by overwriting that place with your assignment to 12.
Since the pointer returned was immediately used, in this case you could get away with returning a local pointer. However, it is bad practice because if that pointer was reused after another function call reused that memory in the stack, the behavior of the program would be undefined.
int *fun()
{
int point;
point = 12;
return (&point);
}
or almost identically:
int *fun()
{
int point;
int *point_ptr;
point_ptr = &point;
*point_ptr = 12;
return (point_ptr);
}
Another bad practice but safer method would be to declare the integer value as a static variable, and it would then not be on the stack and would be safe from being used by another function:
int *fun()
{
static int point;
int *point_ptr;
point_ptr = &point;
*point_ptr = 12;
return (point_ptr);
}
or
int *fun()
{
static int point;
point = 12;
return (&point);
}
As others have mentioned, the "right" way to do this would be to allocate memory on the heap, via malloc.
It is not allocating memory at assignment of value 12 to integer pointer. Therefore it crashes, because it's not finding any memory.
You can try this:
#include<stdio.h>
#include<stdlib.h>
int *fun();
int main()
{
int *ptr;
ptr=fun();
printf("\n\t\t%d\n",*ptr);
}
int *fun()
{
int ptr;
ptr=12;
return(&ptr);
}
To my knowledge the use of the keyword new, does relatively the same thing as malloc(sizeof identifier). The code below demonstrates how to use the keyword new.
void main(void){
int* test;
test = tester();
printf("%d",*test);
system("pause");
return;
}
int* tester(void){
int *retMe;
retMe = new int;//<----Here retMe is getting malloc for integer type
*retMe = 12;<---- Initializes retMe... Note * dereferences retMe
return retMe;
}