I have written a function to allocate memory for an array and store the array length in a pointer so I can use both in my main function. Everything seems to work fine until I try to loop through the array printing the values.
When I use the array size pointer to terminate the print loop it shows strange behaviour. Could you please show me where I am going wrong?
Thanks in advance :)
#include <stdio.h>
#include <stdlib.h>
void func (int** arr, int** len){
int length = 5;
*len=&length;
*arr = malloc(sizeof(int)*(**len));
for (int i=0; i<(**len); i){
(*arr)[i]=i*10;
}
}
int main(){
int* len = NULL;
int* arr = NULL;
func(&arr, &len);
for (int i=0; i<5; i){
printf("%d\n", arr[i]);
} //works
/*
for (int i=0; i<*len; i){
printf("%d\n", arr[i]);
} //doesnt work
*/
free(arr);
return 0;
}
CodePudding user response:
int length = 5;
*len=&length;
You here assign *len
to point at a local variable (length
). The local variable length
will go out of scope when the function returns and dereferencing the pointer after that will have undefined behavior.
You'd get the correct behavior if you instead allocate the memory for the int
in main
and provide a pointer to that memory to func
.
#include <stdio.h>
#include <stdlib.h>
void func(int** arr, int* len) { // int* instead
int length = 5;
*len = length;
*arr = malloc(length * sizeof **arr);
for (int i = 0; i < length; i) {
(*arr)[i] = i * 10;
}
}
int main() {
int len; // automatic storage
int* arr = NULL;
func(&arr, &len);
for (int i = 0; i < len; i) {
printf("%d\n", arr[i]);
} // now works
free(arr);
}
CodePudding user response:
for (int i=0; i<*len; i){
printf("%d\n", arr[i]);
}
The above code doesn't work because the contents of len
are indeterminate.
Using
*
with an indeterminate orNULL
pointer has undefined behaviour.If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
In the function func
, lenght
is a local variable, which is destroyed once the function returns.
- The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.
- Identifiers only have visibility inside their scope, starting at their declarations.
- Unless they are
VLA
OR temporary objects, automatic variables have a lifetime corresponding to the execution of their block of definition.
As the lenght
is known at compile time and never changes, there's no need to pass a pointer to pointer to an int
. Just pass an int
for the allocation.
CodePudding user response:
You should have worked correctly with the pointer. You passed a pointer to a pointer to a function and you're trying to write a value to the pointer.
int a = 0;
fun(&a);
{
*a = 42;
}
#include <stdio.h>
#include <stdlib.h>
void func (int** arr, int* len){
int length = 5;
*len=length;
*arr = malloc(sizeof(int)*(*len));
for (int i=0; i<(*len); i)
{
(*arr)[i]=i*10;
}
}
int main(){
int len = 0;
int* arr = NULL;
func(&arr, &len);
for (int i=0; i<5; i){
printf("%d\n", arr[i]);
} //works
for (int i=0; i<len; i){
printf("%d\n", arr[i]);
} //doesnt work
free(arr);
return 0;
}