0

I have passed pointer to a pointer as a parameter to function and the goal is to make an array inside of that function. I have done that step properly and also inside of the function checked the *address and value of the array(local) as well as pointed by the pointer(op_ptr_array_) and they are the same(as desired).

But the problem is occurring while I want to dereference the provided pointer(op_ptr_array). The values are wrong while addresses are matched with the pointed array(local).

My idea is that as the address of op_ptr_array(pointer passed to the function) is equal to the local and op_ptr_array_ (array and pointer inside of the function) so using a for loop *(op_ptr_array+i) will provide me the result where i < op_size.

The approach I have taken is as follows:


#include <iostream>

void op_calculation(unsigned int*  ip_ptr_array_,
                    unsigned int   ip_size_,
                    unsigned int** op_ptr_array_,
                    unsigned int*  op_size_)
{
    *(op_size_) = ip_size_ + 2;
    std::cout<<"op_size_ address: "<<op_size_<<std::endl;
    std::cout<<"op_size_ value: "<<*(op_size_)<<std::endl;

    unsigned int local[*(op_size_)];
    std::cout<<"making local array to be pointed by op_ptr_array_\n";
    for (unsigned int i = 0; i< *(op_size_); i++)
    {
        local[i]=i+1*3;
        std::cout<<local[i]<<" ";
    }
    std::cout<<"\n";
    *op_ptr_array_ = &local[0];
    local[3] = 87; // for checking pointer charecter
    for (unsigned int i = 0; i < *(op_size_); i++)
        std::cout<<"array address: "<<&local[i]<<" ,op_ptr_array address: "<<(*op_ptr_array_)+i<<" ,val of array: "<<local[i]<<" ,val at op_ptr_array: "<<*((*op_ptr_array_)+i)<<std::endl;
        // here value and addresses are same which is desired
}

int main()
{
    unsigned int ip_size = 10;
    unsigned int* ip_ptr_array = new unsigned int[ip_size];

    unsigned int op_size;
    unsigned int* op_ptr_array;

    for(unsigned int i = 0; i < ip_size; i++)
    {
        ip_ptr_array[i] = i+2*2;
    }

    op_calculation(ip_ptr_array,
                ip_size,
                &op_ptr_array,
                &op_size);
    
    std::cout<<"Value printing after operation of op_calculation function\n";
    std::cout<<"op_size: "<<op_size<<std::endl;

    std::cout<<"op_ptr_array\n";
    for(unsigned int i = 0; i < op_size; i++)
        std::cout<<"Address: "<<(op_ptr_array+i)<<" , Value: "<<*(op_ptr_array+i)<<"\n";
        /* Here only addresses are same with `local array` and
        address pointed by op_ptr_array_ pointer` which you will find in op_calculation
        function but values are different*/
    std::cout<<"\n";

    return 0;
}

Any idea where I am making the mess is highly appreciable.

user10634362
  • 549
  • 5
  • 21

1 Answers1

1

Variable local is being declared as a local variable (i.e. on the stack). This falls out of scope when the function op_calculation exits, which means that the memory originally used to allocate local may be used for something else.

This can be corrected by converting local to a pointer and using new to allocate memory for the array’s contents or by declaring local as static, which will place the contents elsewhere in RAM. Keep in mind, if you use static any future calls to op_calculation will overwrite the contents of the array, even if it is still in use elsewhere. This would not be a problem if you used new, but if you use new you will need to remember to deallocate the array using delete[] when it is no longer needed.

Jonathon S.
  • 1,928
  • 1
  • 12
  • 18
  • What I have understood by reading your answer is that--- I have declared `local` as like as follows. `unsigned int* local = new unsigned int[*(op_size_)];` In this case **dereferencing** works. But my ques is in which section I will call now `delete [] local`? If I call it at the end of `op_calculation` function without any doubt it will cause error. – user10634362 Sep 03 '21 at 13:13
  • 1
    Yes, this is correct. Sorry, I mentioned `malloc` in the answer, but you are in C++ so you would use `new`. You will no longer have access to `local` once `op_calculation ` exits, but you can deallocate using `delete[] op_ptr_array;` The `delete[]` keyword operates on a pointer to an array and will deallocate whatever is being pointed to. – Jonathon S. Sep 03 '21 at 13:30
  • But, I have declared `unsigned int* op_ptr_array;`. Can I do `delete [] op_ptr_array;` for this? I am not sure the declaration is here dynamically allocated memory or not(As far I have read `delete` operator I can use if I declare anything with `new`). Maybe I can use `delete op_ptr_array;`(without square braces). Though both have compiled without error but don't understand what is the correct logic/ process to follow. – user10634362 Sep 03 '21 at 14:13
  • The pointer stored in `op_ptr_array` would have been created by `new`, which is what will be used by the `delete[]` operator to deallocate when you use delete on `op_ptr_array`. There is a little bit of detail on how `delete[]` works here: https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array. – Jonathon S. Sep 03 '21 at 14:17
  • ok, now I have understood. so, if I say,`op_ptr_array` is pointing to `op_ptr_array_` and `op_ptr_array_` is pointing to `local`, is it correct? Besides, Now I have an issue while I execute the binary with `valgrind`. Still, it cannot free all heap memory (`still reachable: 32 bytes in 1 blocks`). – user10634362 Sep 03 '21 at 14:27
  • Basically yes. You would allocate local with new `unsigned int* local = new unsigned int[*(op_size_)];` inside of the function. Then assign it to `op_ptr_array` when you dereference parameter `op_ptr_array_` in statement ` *op_ptr_array_ = &local[0]; ` inside of the function. So the pointer will then be stored in `opt_ptr_array` when the function returns to `main`. As a side note, you could replace `&local[0]` with `local`, as they are effectively the same thing. – Jonathon S. Sep 03 '21 at 14:45
  • Can you kindly take a look [here](https://coliru.stacked-crooked.com/a/aa8ffa22978da139)? It is throwing me a `memory leak error` while executing the binary by `valgrind ./main`. – user10634362 Sep 03 '21 at 14:57
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/236738/discussion-between-jonathon-s-and-user10634362). – Jonathon S. Sep 03 '21 at 15:10