Home > Blockchain >  How to copy an array that has been initialized as an smartpointer?
How to copy an array that has been initialized as an smartpointer?

Time:12-17

I am using std::unique_ptr<uint8[]> CPPPixelBuffer; to store pixel data of a texture as an array.

This array is initialized in the constructor as followed:

SIZE_T BufferSize = WorldTextureWidth * WorldTextureHeight * DYNAMIC_TEXTURE_BYTES_PER_PIXEL;
CPPPixelBuffer = std::make_unique<uint8[]>(BufferSize);

The creation and drawing of the texture is working so far. (as shown on the picture below) TextureData as the are supposed to be

Now I am trying to create a copy of that array using a for loop. (I am using a for loop because I want to extract just parts of the texture later on. But just for demonstration I copy the array completly in this example.)

SIZE_T PartBufferSize = WorldTextureWidth * WorldTextureHeight * DYNAMIC_TEXTURE_BYTES_PER_PIXEL;
std::shared_ptr<uint8[]> PartPixelBuffer(new uint8[PartBufferSize]());

// Get the base pointer of the pixel buffer
uint8* Ptr = CPPPixelBuffer.get();

//Get the base pointer to the new pixel buffer
uint8* PartPtr = PartPixelBuffer.get();

for (int i = 0; i < WorldTextureHeight *WorldTextureWidth * DYNAMIC_TEXTURE_BYTES_PER_PIXEL; i  ) {

        *(PartPtr  ) = *(Ptr  );
}

delete Ptr;
delete PartPtr;

The pixels after copying are mixed up and the picture is different every time I execute this code. (as shown on the picture below) Wrong Reults

What am I doing wrong?

CodePudding user response:

The last two lines are triple wrong.

  1. the arrays are managed by smart pointers. You should not delete them manually.
  2. the arrays are created via new[]. Freeing the memory would need delete[]
  3. the pointers are not pointing to the beginning of the array, because they have been incremented in the loop

Each point alone would cause undefined behavior.

You should remove the last two lines. It is unclear why you think you would need to detele the original and the copy after copying the data. The copying itself looks ok (though there are simpler way to copy the array as mentioned in comments).

CodePudding user response:

Firstly, you use arrays that managed by smartpointers. This means, that you don't need to call delete to free memory, these pointers will be freed when they will be out-of-scope. Secondly, while coding in C , use std::vector instead of raw arrays, because it has some advantages like better safety. Thirdly, if you use smartpointers, then do not allocate memory explicitly, use functions that will do that for you. In your case, you might want to use std::make_shared<>(). This is example of code, where I create one smartpointer to std::vector, that stores uint8_t, and after that, I copy that pointer to another pointer:

#include <iostream>
#include <memory>
#include <vector>

int main(int argc, char* argv[])
{

    auto ptr1 = std::make_shared<std::vector<uint8_t>>();
    auto ptr2 = ptr1;

    std::cout << ptr1 << '\n';
    std::cout << ptr2 << '\n';

    return 0;
}

This will print addresses of memory which smartpointers are pointing to. Note that every run of program you will see different memory addresses, but these two addresses will be the same. If you want to copy array when using smartpointers, you can do this trick:

#include <iostream>
#include <memory>
#include <vector>

int main(int argc, char* argv[])
{

    auto ptr1 = std::make_shared<std::vector<uint8_t>>();
    std::vector<uint8_t> vec = *ptr1;

    std::cout << ptr1 << '\n';
    std::cout << &vec << '\n';

    

    return 0;
}

This trick will let you to copy array. When running that code, array which is pointed by ptr1 and vec will be equal, but with different memory addresses.

  • Related