1

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;
}
2
  • 2
    *len=&length; You are storing the address of a local variable in that pointer. This variable does not exist any longer when you leave that function. Accessing it is illegal. Why do you want a pointer to store the length. It is just a numerical value. You should change to int * len in parameter list and in main use int len = 0; Commented Jan 14, 2023 at 10:52
  • malloc does not accept a pointer to a pointer, it returns a pointer. Functions may, and generally do, return values. Use that to your advantage, Commented Jan 14, 2023 at 12:43

3 Answers 3

1
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);
}
Sign up to request clarification or add additional context in comments.

Comments

1
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 or NULL 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, and retains its last-stored value throughout its lifetime.²

  • For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.³

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.

[1], [2], [3] — C11, 6.2.4 Storage Duration of Objects.

1 Comment

You should cite sources for quoted material, both to give credit to the authors and so that other people can look it up and understand its context. You appear to have mixed material from several sources, and some of it is authoritative and some is not.
0

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;
}

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.