memcpy copies more than expected when using modern C++ syntax - c++

int vertexCount = 5;
std::vector<DirectX::XMVECTOR> vertices(vertexCount);
for (int i = 0; i < vertexCount; ++i) {
vertices[i] = DirectX::XMVectorSet(i, i, i,0);
}
/*1-*/ std::shared_ptr<void> vertexData = std::make_shared<DirectX::XMVECTOR*>(new DirectX::XMVECTOR[vertexCount]);; //this works
/* 2-*/ std::shared_ptr<void> vertexData = std::make_shared<std::vector<DirectX::XMVECTOR>>(vertexCount); // this doesnt work why??
memcpy(vertexData.get(), pxVertices.data(), vertexCount * sizeof(DirectX::XMVECTOR));
when I use C-style array syntax memcpy works fine, but when I create the shared pointer using modern C++ style I get an overflow, I mean in this example the new capacity is [capacity] = 66584576, before the memcpy it had size of 5 !
so what went wrong?

Related

How to use memset or fill_n to initialize a dynamic two dimensional array in C++

I have a 2D array created dynamically.
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
}
I want to fill the array with some value (say 1). I can loop over each item and do it.
But is there a simpler way. I am trying to use memset and std::fill_n as mentioned in this post.
std::fill_n(abc, rows * cols, 1);
memset(abc, 1, rows * cols * sizeof(int));
Using memset crashes my program. Using fill_n gives a compile error.
invalid conversion from 'int' to 'int*' [-fpermissive]
What am I doing wrong here ?
You could just use vector:
std::vector<std::vector<int>> abc(rows, std::vector<int>(cols, 1));
You cannot use std::fill_n or memset on abc directly, it simply will not work. You can only use either on the sub-arrays:
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(abc[i], cols, 1);
}
Or make the whole thing single-dimensional:
int *abc = new int[rows * cols];
std::fill_n(abc, rows*cols, 1);
Or I guess you could use std::generate_n in combination with std::fill_n, but this just seems confusing:
int **abc = new int*[rows];
std::generate_n(abc, rows, [cols]{
int* row = new int[cols];
std::fill_n(row, cols, 1);
return row;
});
I think that your main problem here is that you don't have an array of int values. You have an array of pointers to ints.
You probably should start with int* abc = new int[rows * cols]; and work from there, if I understand what you are trying to achieve here.
Just use with * inside the loop you already have:
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(*(abc+i), cols, sizeof(int));
}
fill_n don't know where the memory maps the new int array, so you must be carefully coding that way.
I recommend to read:
A proper way to create a matrix in c++
Since you've already got good, workable answers to solve your problem, I want to add just two pointers left and right from the standard path ;-)
a) is just a link to the documentation of Boost.MultiArray
and b) is something I don't recommend you use, but it might help you to understand what you've initially tried. And since your profile shows visual studio tags, you might come in contact with something like this in the win32 api. If that is the case the documentation usually tells you not to use free()/LocalFree()/... on the elements and the "outer" pointer-pointer but to use a specialized function.
(note: I'm not trying to make this code look pretty or clever; it's a mishmash of c and a little c++-ish junk ;-))
const std::size_t rows = 3, cols =4;
int main()
{
std::size_t x,y;
// allocate memory for 0...rows-1 int* pointers _and_ cols*rows ints
int **abc = (int**)malloc( (rows*sizeof(int*)) + cols*rows*sizeof(int) );
// the memory behind abc is large enough to hold the pointers for abc[0...rows-1]
// + the actual data when accessing abc[0...rows-1][0....cols-1]
int* data = (int*)((abc+rows));
// data now points to the memory right after the int*-pointer array
// i.e. &(abc[0][0]) and data should point to the same location when we're done:
// make abc[0] point to the first row (<-> data+(cols*0)), abc[1] point the second row (<-> data+(cols*1)....
for(y=0;y<rows; y++) {
abc[y] = &(data[y*cols]);
}
// now you can use abc almost like a stack 2d array
for(y=0; y<rows; y++) {
for (x=0; x<cols; x++) {
abc[y][x] = 127;
}
}
// and -since the memory block is continuos- you can also (with care) use memset
memset(&abc[0][0], 1, sizeof(int)*rows*cols);
// and with equal care ....
std::fill_n( &(abc[0][0]), rows*cols, 127);
// and get rid of the whole thing with just one call to free
free(abc);
return 0;
}

c++ array of uint8 buffers

In C++, I have an uint8 buffer of the length [len]. When allocating a single buffer I do this:
uint8 *buffer= new uint8[len];
What's the syntax for allocating an array of such buffers? This gives me a syntax error:
uint8** buffers = new uint8[len]*[bufferCount];
The way you initialize a 2d array is as follows:
uint8** buffers = new uint8*[bufferCount];
for (int i = 0; i < bufferCount; i++)
buffers[i] = new uint8[len];
#include <vector>
using byte_vector = std::vector<uint8_t>;
using byte_vector_vector = std::vector<byte_vector>;
// example of a 1-dimension vector
auto v1 = byte_vector(len, inital_value);
// example of a [2, len] vector
auto v_of_v = byte_vector_vector {
byte_vector(len, initial_value),
byte_vector(len, initial_value)
};
// print the uint8 at (0,1)
std::cout << v_ov_v[0][1] << std::endl;
You asked
What's the syntax for allocating an array of such buffers?
You can use:
uint8** buffers = new uint8*[bufferCount];
However, use this only if std::vector is absolutely not an option for some reason.

C++ - place multiple images in an array pointer

I have been trying to read ten images stored on the disk into an array pointer using the SOIL library. I would like to then render the resulting data in OpenGL using 3D textures.
The code I wrote to read images from the disk and store them in a buffer throws up Access violation reading location 0x00000000 errors.
Is this the right way of storing multiple images using SOIL into an array pointer?
unsigned char *tex;
int imSize = h*w;
unsigned char *buff = new unsigned char[h * w * slices];
for(int i = 1; i<=10; i++)
{
for(int j = 0; j<imSize; j++)
{
if (i==1)
{
tex = (unsigned char*) SOIL_load_OGL_texture("Data/PA_170090.png",
SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID,SOIL_FLAG_INVERT_Y);
buff[((i-1)*imSize) + j] = tex[j]; }
if (i==2)
{ tex = (unsigned char*)SOIL_load_OGL_texture("Data/PA_170091.png",
SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
buff[(i-1)*imSize + j] = tex[j]; }
if (i==3)
{ tex = (unsigned char*)SOIL_load_OGL_texture("Data/PA_170092.png",
SOIL_LOAD_AUTO,SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
buff[(i-1)*imSize + j] = tex[j];}
....
.... // up to 10 images
}
}
It seems SOIL_load_OGL_texture, is not returning any buffer. Instead, it returns an Id (of type GLuint , which is unsigned int). If the function fails, the id will be zero. You are casting that integer value to a pointer and dereferencing it, which results in access violation.

Sometimes I get EXEC_BAD_ACCESS (Access violation) when reversing an array

I am loading an image using the OpenEXR library.
This works fine, except the image is loaded rotated 180 degrees. I use the loop shown below to reverse the array but sometimes the program will quit and xcode will give me an EXEC_BAD_ACCESS error (Which I assume is the same as an access violation in msvc). It does not happen everytime, just once every 5-10 times.
Ideally I'd want to reverse the array in place, although that led to errors everytime and using memcpy would fail but without causing an error, just a blank image. I'd like to know what's causing this problem first.
Here is the code I am using: (Rgba is a struct of 4 "Half"s r, g, b, and a, defined in OpenEXR)
Rgba* readRgba(const char filename[], int& width, int& height){
Rgba* pixelBuffer = new Rgba[width * height];
Rgba* temp = new Rgba[width * height];
// ....EXR Loading code....
// TODO: *Sometimes* the following code results in a bad memory access error. No idea why.
// Flip the image to conform with OpenGL coordinates.
for (int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
temp[(i*width)+j] = pixelBuffer[(width*height)-(i*width)+j];
}
}
delete pixelBuffer;
return temp;
}
Thanks in advance!
Change:
temp[(i*width)+j] = pixelBuffer[(width*height)-(i*width)+j];
to:
temp[(i*width)+j] = pixelBuffer[(width*height)-(i*width)+j - 1];
(Hint: think about what happens when i = 0 and j = 0 !)
And here's how you can optimize this code, to save memory and for cycles:
Rgba* readRgba(const char filename[], int& width, int& height)
{
Rgba* pixelBuffer = new Rgba[width * height];
Rgba tempPixel;
// ....EXR Loading code....
// Flip the image to conform with OpenGL coordinates.
for (int i = 0; i <= height/2; i++)
for(int j = 0; j < width && (i*width + j) <= (height*width/2); j++)
{
tempPixel = pixelBuffer[i*width + j];
pixelBuffer[i*width + j] = pixelBuffer[height*width - (i*width + j) -1];
pixelBuffer[height*width - (i*width + j) -1] = tempPixel;
}
return pixelBuffer;
}
Note that optimal (from a memory usage best practices point of view) would be to pass pixelBuffer* as a parameter and already allocated. It's a good practice to allocate and release the memory in the same piece of code.

C++ vector element is different when accessed at different times

I'm developing a 3D game using SDL and OpenGL on Ubuntu 9.04 using Eclipse CDT. I've got a class to hold the mesh data in vectors for each type. Such as Vertex, Normal, UVcoord (texture coordinates), as well as a vector of faces. Each face has 3 int vectors which hold indexes to the other data. So far my game has been working quite well at rendering at nice rates. But then again I only had less then one hundred vertexes among two objects for testing purposes.
The loop accessing this data looks like this:
void RenderFace(oFace face)
{
/*
* More Stuff
*/
oVertice gvert;
oUVcoord tvert;
oNormal nvert;
for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
{
gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);
tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);
nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);
glNormal3f(nvert.X, nvert.Y, nvert.Z);
glTexCoord2f(tvert.U, tvert.V);
glVertex3f(scale * gvert.X, scale * gvert.Y, scale * gvert.Z);
}
/*
* More Stuff
*/
}
There is a loop that calls the renderFace() function which includes the above for loop. The minus one is because Wavefront .obj files are 1 indexed (instead of c++ 0 index). Anyway, I discovered that once you have about 30 thousand or so faces, all those calls to glVertex3f() and the like slow the game down to about 10 FPS. That I can't allow. So I learned about vertex arrays, which require pointers to arrays. Following the example of a NeHe tutorial I continued to use my oVertice class and the others. Which just have floats x, y, z, or u, v. So I added the same function above to my OnLoad() function to build the arrays which are just "oVertice*" and similar.
Here is the code:
bool oEntity::OnLoad(std::string FileName)
{
if (!obj.OnLoad(FileName))
{
return false;
}
unsigned int flsize = obj.TheMesh.GetFaceListSize();
obj.TheMesh.VertListPointer = new oVertice[flsize];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
obj.TheMesh.NormListPointer = new oNormal[flsize];
oFace face = obj.TheMesh.GetFace(0);
oVertice gvert;
oUVcoord tvert;
oNormal nvert;
unsigned int counter = 0;
unsigned int temp = 0;
for (unsigned int flIndex = 0; flIndex < obj.TheMesh.GetFaceListSize(); flIndex++)
{
face = obj.TheMesh.GetFace(flIndex);
for (unsigned int fvIndex = 0; fvIndex < face.GeoVerts.size(); fvIndex++)
{
temp = face.GeoVerts[fvIndex];
gvert = obj.TheMesh.GetVertice(face.GeoVerts[fvIndex] - 1);
temp = face.UV_Verts[fvIndex];
tvert = obj.TheMesh.GetUVcoord(face.UV_Verts[fvIndex] - 1);
temp = face.NrmVerts[fvIndex];
nvert = obj.TheMesh.GetNormal(face.NrmVerts[fvIndex] - 1);
obj.TheMesh.VertListPointer[counter].X = gvert.X;
obj.TheMesh.VertListPointer[counter].Y = gvert.Y;
obj.TheMesh.VertListPointer[counter].Z = gvert.Z;
obj.TheMesh.UVlistPointer[counter].U = tvert.U;
obj.TheMesh.UVlistPointer[counter].V = tvert.V;
obj.TheMesh.NormListPointer[counter].X = nvert.X;
obj.TheMesh.NormListPointer[counter].Y = nvert.Y;
obj.TheMesh.NormListPointer[counter].Z = nvert.Z;
counter++;
}
}
return true;
}
The unsigned int temp variable is for debugging purposes. Apparently I don't have a default constructor for oFace that doesn't have something to initialize with. Anyway, as you can see it's pretty much that same exact routine. Only instead of calling a gl function I add the data to three arrays.
Here's the kicker:
I'm loading a typical cube made of triangles.
When I access element 16 (0 indexed) of the UV_Verts vector from the RenderFace() function I get 12.
But when I access element 16 (0 indexed) of the same UV_Verts vector from the OnLoad() function I get something like 3045472189
I am so confused.
Does anyone know what's causing this? And if so how to resolve it?
One possible reason could be that you're creating arrays with size flsize:
obj.TheMesh.VertListPointer = new oVertice[flsize];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize];
obj.TheMesh.NormListPointer = new oNormal[flsize];
but use the arrays with indices up to flsize * face.GeoVerts.size
for (...; flIndex < obj.TheMesh.GetFaceListSize(); ...) { // flsize = GetFaceListSize
for (...; fvIndex < face.GeoVerts.size(); ...) {
...
obj.TheMesh.UVlistPointer[counter].U = ...;
...
counter++;
}
}
so your array creation code should actually be more like
obj.TheMesh.VertListPointer = new oVertice[flsize * face.GeoVerts.size()];
obj.TheMesh.UVlistPointer = new oUVcoord[flsize * face.GeoVerts.size()];
obj.TheMesh.NormListPointer = new oNormal[flsize * face.GeoVerts.size()];