• Advertisement
Sign in to follow this  

Troble with double pointer memory allocation

Recommended Posts

Hi everyone!
So my question should be fairly simple, yet i couldn't seem to find any documentation on the topic.
As seen below, my problem is that i want to create an array of vertex buffers in Direct X 11. From my experience when using double pointers with classes and structs, this memory copy method has always worked out for me since the classes hold the same memory data structure.
Yet when using DirectX own buffer interface, this type of copy does not work and gives me access violation.
Can someone please explain to me why this is and is there a solution to how to store the old information when expanding the current array?

    void BindDataToBuffer(ID3D11Device* gDevice, ID3D11Buffer** &gVertexBufferArray, FBXData &FBX)
	{
		HRESULT hr;

		if (gVertexBufferArray != nullptr)
		{
			ID3D11Buffer** tempBuffer = new ID3D11Buffer*[this->totalSumMeshes + FBX.meshCount];
			tempBuffer = { nullptr };
		
			for (int i = 0; i < this->totalSumMeshes; i++)
			{
				tempBuffer[i] = gVertexBufferArray[i];
			}

			gVertexBufferArray = tempBuffer;

			this->totalSumMeshes += FBX.meshCount;

Share this post


Link to post
Share on other sites
Advertisement

Yet when using DirectX own buffer interface, this type of copy does not work and gives me access violation.

Which line? tempBuffer = gVertexBufferArray?

Yes :) that line! Sorry if i wasn't clear enough

Share this post


Link to post
Share on other sites
ID3D11Buffer** tempBuffer = new ID3D11Buffer*[this->totalSumMeshes + FBX.meshCount];
tempBuffer = { nullptr };

This isn't safe. It's probably not the actual problem. But ID3D11Buffer does not actually delete it's self.

You're creating data in your heap, and then lost the ability to delete it.

Even if this was correct, this still shouldn't work. Reason at the end.

			for (int i = 0; i < this->totalSumMeshes; i++)
			{
				tempBuffer[i] = gVertexBufferArray[i];
			}

So you're copying pointers into your tempBuffer now.

gVertexBufferArray = tempBuffer;

Not entirely sure what's going on here. This seems utterly redundant.

 

But anyways...

The function you need to correctly create a buffer in Directx 11 is... CreateBuffer(...) Create buffer will give you I11D3DBuffer objects that have been correctly created and initialized on the device.

 

I also don't believe that I11D3DBuffer is safe to actually copy, as it's data is typically managed by the Driver.

Edited by Tangletail

Share this post


Link to post
Share on other sites
gVertexBufferArray = tempBuffer; Not entirely sure what's going on here. This seems utterly redundant.

 

Note the paremeter type: ID3D11Buffer** &gVertexBufferArra

 

 

The function you need to correctly create a buffer in Directx 11 is... CreateBuffer(...) Create buffer will give you I11D3DBuffer objects that have been correctly created and initialized on the device.

That is not important here. He just allocates an array of pointers, sets pointers equal to nullptr or some other pointer. Who cares what the type of the pointee is. (The method would be identical if one would use int * instead of ID3D11Buffer *)

 

Edited by matt77hias

Share this post


Link to post
Share on other sites

As far as I can see, the piece of code you provide should work.

A small test with "int" (instead of "ID3D11Buffer"). (Note the obvious memory leak as well).

#include <iostream>


typedef int TYPE;


void exchange(TYPE *&values, size_t old_size, size_t extra_size) {
    TYPE *new_values = new TYPE[old_size + extra_size];
    for (size_t i = 0; i < old_size; ++i) {
        new_values[i] = values[i];
    }
    for (size_t i = old_size; i < old_size + extra_size; ++i) {
        new_values[i] = 0;
    }
    values = new_values;
}


int main() {
 TYPE *values = new TYPE[5];


 for (size_t i = 0; i < 5; ++i) {
    values[i] = i+1;
 }
   
 exchange(values, 5, 10);


 for (size_t i = 0; i < 5; ++i) {
    std::cout << values[i];
 }
 for (size_t i = 5; i < 10; ++i) {
    std::cout << values[i];
 }
}

Share this post


Link to post
Share on other sites

I solved the problem! Thank you guys! :)
So my solution to the problem was simple, i solely removed the " tempBuffer = { nullptr }; " line.
Solution:

void BindDataToBuffer(ID3D11Device* gDevice, ID3D11Buffer** &gVertexBufferArray, FBXData &FBX)
	{
		HRESULT hr;

		if (gVertexBufferArray != nullptr)
		{
                        ID3D11Buffer** tempBuffer = new ID3D11Buffer*[this->totalSumMeshes + FBX.meshCount];
		
			for (int i = 0; i < this->totalSumMeshes; i++)
			{
				tempBuffer[i] = gVertexBufferArray[i];
			}

			gVertexBufferArray = tempBuffer;

			this->totalSumMeshes += FBX.meshCount;

Explanation:

My concept was to create a vertex buffer array for each mesh loaded into the project.
The meshes was loaded in from a file format i created myself.
So when i loaded in another file, i wanted to expand the existing array in size without overwriting existing stored data.
Since the ID3DBuffer is a virtual class, i needed to create the ID3DBuffer as a double pointer.
Why? When creating with double pointers, you create an array of interface pointers.
So comparing that to simple data types like int* and int**, the int* is structured like int[x] and int** like int[x][y], but because the interface** is virtual we do NOT get buffer[x][y] but we receive buffer[x] because a single pointer only points to the memory location of the object.

int* == int[x];
int** == int[x][y];

ID3DBuffer* == ID3DBuffer;
ID3DBuffer** == ID3DBuffer[x];

With that in note, when transfering the adress of the data between the two buffers, we want to make sure that the newly created temporary buffer is not a null pointer.
Why? Because otherwise the memory of the pointer would just be set to 0 and therefore we can't give it new adresses since it lacks memory locations to store the adresses in.

for (int i = 0; i < this->totalSumMeshes; i++)
    {
        tempBuffer[i] = gVertexBufferArray[i];
    }

And the:

gVertexBufferArray = tempBuffer;

Is because we want the old array to store new array size we created.
Note:
We do NOT want to delete[] the temp array since the old and the new now hold the same adresses.
Deleting will result in doing so for both the arrays.
The deletion of the memory will be set in the end of the program or when you dont need the array anymore.
And in that case we want to use release, not delete.

Share this post


Link to post
Share on other sites

The line you removed was just replacing the allocated pointer with an anonymous local array.

You definitely do not understand pointers, memory life time and ownership. I would advice you to use standard container like vector and to have a zero new policy ( make_unique is fine ), and no raw pointers, use comptr for dx objects.

You will save you time, performance, simplify design, reduce complexity, and save baby seals  :)

Edited by galop1n

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement