image pointer to pointer initialization in C++ - c++

I meet a problem when dealing with image initialization.
I have a class like this:
Class MyImage
{
private:
unsigned int** image;
const unsigned int w;
const unsigned int h;
public:
MyImage(unsigned int** _image,unsigned int _w,
unsigned int _h); // copy constructor
}
it seems if I use copy constructor as above, I need to delete image first like below:
MyImage(unsigned int** _image,unsigned int _w,unsigned int _h)
{
if (image)
{
for (int i = 0;i < w;++i)
delete[] image[i];
delete[] image;
}
// .. copy _image to imge
}
however if w and h are const members, it seems w and h must be initialized in the inialization list, like below:
MyImage(unsigned int** _image,unsigned int _w,unsigned int _h): w(_w),h(_h)
{
// ..code
}
then I can't delete image because w changes before it. My Question is what should I do if I don't want to eliminate const decoration in w and h? Any method? Thanks.

This is not a copy-constructor
MyImage(unsigned int** _image,unsigned int _w,unsigned int _h)
This is a copy-constructor
MyImage(const MyImage &image)
Don't use : w(_w) and first delete previous image, then use w = image._w.
However, you don't need delete anything because it's a constructor.

Use an encapsulated std::vector to manager the image data. The default copy constructor, move constructor, assignment operator, move assignment operator and default destructor will all be automatically generated for you and do the right things. Further by allocating the image data in a continuous block of memory and using a stride over row (or column) major order, it will be far more efficient than allocating a new memory block for every line...
struct MyImage
{
const size_t w, h;
vector<int> image;
MyImage(const vector<int>& image, size_t w, size_t h)
: image(image)
, w(w)
, h(h)
{
assert(image.size() == w*h);
}
MyImage(vector<int>&& image, size_t w, size_t h)
: image(move(image))
, w(w)
, h(h)
{
assert(image.size() == w*h);
}
int& pixel(size_t x, size_t y) { return image[w*y+x]; }
int pixel(size_t x, size_t y) const { return image[w*y+x]; }
};

In your case, there is nothing wrong with w and h being a const. You can write your constructor in the following way:
MyImage(unsigned int** _image,unsigned int _w,unsigned int _h)
: w(_w), h(_h)
{
// No data is allocated in the memory pointed to by image yet
// We have to allocate it here. Remember, that copy-ctor is
// a constructor, so it operates on newly created instance,
// not on an existing one.
image = new unsigned int * [h];
for (int i = 0; i < h; i++)
{
image[i] = new unsigned int [w];
memcpy(image[i], _image[h], w * sizeof(unsigned int));
}
}
From my image-processing experience, consider storing an image as a single table, row-by-row. You can access (x, y)-th element by calling data[y * w + x]; In such case, you can simplify your copy ctor:
MyImage::MyImage(unsigned int * source, int newW, int newH)
: w(newW), h(newH)
{
image = new unsigned int[w * h];
memcpy((void *)image, (void *)source, w * h * sizeof(unsigned int));
}
The copy constructor, as C++ community understands this term, would look like this:
MyImage::MyImage(const MyImage &source)
: w(source.w), h(source.h)
{
image = new unsigned int[w * h];
memcpy((void *)image, (void *)source.image, w * h * sizeof(unsigned int));
}
Notice, that the image field does not exist when you call the constructor, so you do not need to free anything.
// Your code
MyImage(unsigned int** _image,unsigned int _w,unsigned int _h)
{
// Class is allocated into some part of memory, which might
// have been used, so in effect this may be actually true,
// because image may contain some rubbish data
if (image)
{
// But this will result mostly likely in Access Violation
// error, because you would try to use (free!) some random
// data in memory.
for (int i = 0;i < w;++i)
delete[] image[i];
delete[] image;
}
// .. copy _image to imge
}
If you need an assign-like method, which copies contents of some image (either stored in a unsigned int * or in another Image class) to an existing instance of Image, w and h cannot be const.

Related

cant figure out how to acces these elements

this is my header
#include <SDL.h>
class Grid
{
public:
int** Cells;
int x;
int y;
SDL_Color* palette[255];
Grid(int,int,int);
~Grid();
void DrawGrid(SDL_Renderer*);
void SetPalette(int c, int r, int g, int b, int a);
};
and this is my source:
Grid::Grid(int a,int b,int s)
{
std::cout << "grid constructed";
x = a;
y = b;
Grid::Cells = (int**) malloc(x*s);
for (int i = 0;i < x;i++)
{
Grid::Cells[i] = (int*)malloc(y*s);
}
SetPalette(1, 255, 255, 255, 0);
}
void Grid::DrawGrid(SDL_Renderer* renderer)
{
std::cout << Grid::palette[Cells[i][o]].r << " : " << Cells[i][o];
SDL_SetRenderDrawColor(renderer, palette[Cells[i][o]].r, palette[Cells[i][o]].g, palette[Cells[i][o]].b, palette[Cells[i][o]].a);
SDL_RenderDrawPoint(renderer, i, o);
}
void Grid::SetPalette(int c, int r, int g, int b, int a)
{
palette[c].r = r;
i have this for green blue and alpha too
}
it says expression must have class type. how do i fix
i have tried hard to figure it out. so i hope i get an answer at least
i did remove some of the irellevant code so it wouldn't take too much space
You did not allocate memory for your palette elements. Without modifying data layout (which is bad, see below), you'll need at least allocate elements in your constructor (prior to SetPalette):
for(int i = 0; i != 255; i++) {
palette[i] = new SDL_Color;
}
(you will also need to release this memory e.g. in destructor).
With palette declared as SDL_Color* palette[255];, expression palette[c] have type SDL_Color*. Accessing structure field with . operator needs structure, not a pointer - so direct solution is palette[c]->r (or manually dereferencing and using ., but that's exactly what -> does).
However allocating a lot of so small objects have a relatively high cost and in given example there is no point to do so. If your palette size is constant (as it is) you could just use SDL_Color palette[255] and remove all allocation/deallocation code (and there will be no need for -> since type of palette[c] is now SDL_Color). If size isn't known at compile time - you can allocate array of colours with a single allocation (malloc or new[]). And if size is changing during runtime, it is probably easier to use vector.

Why does VS clam this violates memory?

I needed to enforce some SSE memory boundaries for the code i'm writing but i'm having some trouble with Visual Studio's memory checker. I'm wondering why VS believes there is memory getting corrupted?
#define sse_t float* __restrict
#include <iostream>
#include <assert.h>
#include <stdio.h>
using namespace std;
class AlignedContainer {
public:
AlignedContainer(int n = 0, int frames = 0, size_t align = 16) {
assert((align & (align - 1)) == 0);
int bufferSize = sizeof(float) * n;
for (int i = 0; i < frames; i++) {
int alignedSize = bufferSize + 15;
auto aqbuf = new unsigned char[alignedSize];
auto aligned = reinterpret_cast < unsigned char *>((reinterpret_cast < size_t > (aqbuf) + 15) & ~15); // 16 bit alignment in preperation for SSE
memset(aqbuf, 0, alignedSize); // for debugging, forces memory to instantly allocate
AcqBuffers.push_back(aqbuf);
displayFrames.push_back(aligned);
}
}
~AlignedContainer() {
for (int i = 0; i < AcqBuffers.size(); i++) {
delete[]AcqBuffers[i];
}
AcqBuffers.empty();
displayFrames.empty();
}
inline sse_t operator [] (int i) const {
return (sse_t) displayFrames[i];
}
private:
vector < void *>displayFrames;
vector < void *>AcqBuffers;
};
int main(int argc, char *argv[])
{
int h = 2160;
int w = 2544;
AlignedContainer ac;
ac = AlignedContainer(h * w, 4);
}
Error at the last line.
/***
*static int CheckBytes() - verify byte range set to proper value
*
*Purpose:
* verify byte range set to proper value
*
*Entry:
* unsigned char *pb - pointer to start of byte range
* unsigned char bCheck - value byte range should be set to
* size_t nSize - size of byte range to be checked
*
*Return:
* TRUE - if all bytes in range equal bcheck
* FALSE otherwise
*
*******************************************************************************/
extern "C" static int __cdecl CheckBytes(
unsigned char * pb,
unsigned char bCheck,
size_t nSize
)
{
while (nSize--)
{
if (*pb++ != bCheck)
{
return FALSE;
}
}
return TRUE;
}
The statement
ac = AlignedContainer(h * w, 4);
first creates a temporary object, that is copied (with the copy-assignment operator) to ac. But because you don't provide the copy-assignment operator, the default one is invoked, and that does just do a shallow copying. So when the temporary object is destroyed the memory allocated by the temporary is deleted, so the ac object have pointers to unallocated memory, which it then tries to delete itself.
You need to read about the rule of three.
When i tried to run your code i discovered the following:
Your code is missing the rvalue assignment operator. Without it, it appears that the content of AcqBuffers gets moved when you call ac = AlignedContainer(h * w, 4);
Somehow the class still hols the content of AcqBuffers (after being moved) deleting it when destroyed. When the destructor of ac gets called then the destructor delets AcqBuffers again causing runtime error.
To fix this you need to add this:
AlignedContainer& operator = (AlignedContainer && rv)
{
displayFrames = std::move(rv.displayFrames);
AcqBuffers = std::move(rv.AcqBuffers);
return (*this);
}
Raxvan.

How to cast from char pointer to custom object pointer

I'm using leveldb to store key-value pairs of integer and MyClass objects. Actually, a key can contain more then one of theses objects.
The problem I have appears when retrieving the data from the database. It compiles, however the values of the MyClass members are not the one I put into the database.
std::string value;
leveldb::Slice keySlice = ANYKEY;
levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
The std::string value1 can now contain only one MyClass object or more. So how do I get them?
I already tried the following which didn't work;
1.) directly typecasting and memcpy
std::vector<MyClass> vObjects;
MyClass* obj = (MyClass*)malloc( value.size());
memcpy((void*)obj, (void*) (value.c_str()), value.size());
MyClass dummyObj;
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
dummyObj = *(obj+i);
vObjects.push_back(dummyObj);
}
2.) reinterpret_cast to void pointer
MyClass* obj = (MyClass*)malloc( value.size());
const void* vobj = reinterpret_cast<const void*>( value.c_str() );
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
const MyClass dummyObj = *(reinterpret_cast<const MyClass*>(vobj)+i);
vObjects.push_back(dummyObj);
}
MyClass is a collection of several public members, e.g. unsigned int and unsigned char and it has a stable size.
I know that there are similar problems with only one object. But in my case the vector can contain more then one and it comes from the leveldb database.
EDIT: SOLUTION
I wrote (de)serialization method for MyClass which then made it working. Thanks for the hint!
void MyClass::serialize( char* outBuff ) {
memcpy(outBuff, (const void*) &aVar, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy(outBuff+c, (const void*) &bVar, sizeof(bVar));
c += sizeof(bVAr);
/* and so on */
}
void MyClass::deserialize( const char* inBuff ) {
memcpy((void*) &aVar, inBuff, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy((void*) &aVar, inBuff+c, sizeof(aVar));
c += sizeof(aVar);
/* and so on */
}
The get method is as follows (put analogously):
int getValues(leveldb::Slice keySlice, std::vector<MyObj>& values) const {
std::string value;
leveldb::Status status = levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
if (!status.ok()) {
values.clear();
return -1;
}
int nValues = value1.size()/sizeof(CHit);
MyObj dummyObj;
for( int i=0; i<nValues; ++i) {
dummyObj.deserialize(value.c_str()+i*sizeof(MyObj));
values.push_back(dummyObj);
}
return 0;
}
You have to serialize your class... otherwise, you're just taking some memory and writing it in leveldb. Whatever you get back is not only going to be different, but it will probably be completely useless too. Check out this question for more info on serialization: How do you serialize an object in C++?
LevelDB does support multiple objects under one key, however, try to avoid doing that unless you have a really good reason. I would recommend that you hash each object with a unique hash (see Google's CityHash if you want a hashing function) and store the serialized objects with their corresponding hash. If your objects is a collection in itself, then you have to serialize all of your objects to an array of bytes and have some method that allows you to determine where each object begins/ends.
Update
A serializable class would look something like this:
class MyClass
{
private:
int _numeric;
string _text;
public:
// constructors
// mutators
void SetNumeric(int num);
void SetText(string text);
static unsigned int SerializableSize()
{
// returns the serializable size of the class with the schema:
// 4 bytes for the numeric (integer)
// 4 bytes for the unsigned int (the size of the text)
// n bytes for the text (it has a variable size)
return sizeof(int) + sizeof(unsigned int) + _text.size();
}
// serialization
int Serialize(const char* buffer, const unsigned int bufferLen, const unsigned int position)
{
// check if the object can be serialized in the available buffer space
if(position+SerializableSize()>bufferLen)
{
// don't write anything and return -1 signaling that there was an error
return -1;
}
unsigned int finalPosition = position;
// write the numeric value
*(int*)(buffer + finalPosition) = _numeric;
// move the final position past the numeric value
finalPosition += sizeof(int);
// write the size of the text
*(unsigned int*)(buffer + finalPosition) = (unsigned int)_text.size();
// move the final position past the size of the string
finalPosition += sizeof(unsigned int);
// write the string
memcpy((void*)(buffer+finalPosition), _text.c_str(), (unsigned int)_text.size());
// move the final position past the end of the string
finalPosition += (unsigned int)_text.size();
// return the number of bytes written to the buffer
return finalPosition-position;
}
// deserialization
static int Deserialize(MyClass& myObject,
const char* buffer,
const unsigned int buffSize,
const unsigned int position)
{
insigned int currPosition = position;
// copy the numeric value
int numeric = *(int*)(buffer + currentPosition);
// increment the current position past the numeric value
currentPosition += sizeof(int);
// copy the size of the text
unsigned int textSize = *(unsigned int*)(buffer + currentPosition);
// increment the current position past the size of the text
currentPosition += sizeof(unsigned int);
// copy the text
string text((buffer+currentPosition), textSize);
if(currentPosition > buffSize)
{
// you decide what to do here
}
// Set your object's values
myObject.SetNumeric(numeric);
myObject.SetText(text);
// return the number of bytes deserialized
return currentPosition - position;
}
};

"dynamic constructor" in c++

i am new to classes in C++ and i need to create a class "Plot" which has a method that reads in data from a file and creates a 3d grid.
i understand that you can make "default" constructors with default values or you can create a special constructor with predefined values.
in my "private" section, i have:
int nx; // number of "x" values
int ny; // number of "y" values
int nz; // number of "z" values
double* grid; // one dimensional array which stores nx*ny*nz values
double tgrid(int ix, int iy, int iz); // function which searches grid and returns value
now, i want to create my "plot" object and then AFTER that, dynamically create the "grid" array. is it possible to do this? or will i need to declare the size of the array "grid" when i first create "plot"?
Use std::vector grid; as your member. Then you can use grid.resize(nx*ny*nz) to force the size you want or use grid.push_back(value); for each value you want to add to the array.
It is possible:
class Plot{
int nx; // number of "x" values
int ny; // number of "y" values
int nz; // number of "z" values
double* grid; // one dimensional array which stores nx*ny*nz values
double tgrid(int ix, int iy, int iz); // function which searches grid and returns value
public:
Plot()
{
grid = NULL;
}
~Plot()
{
delete[] grid;
}
void init(int x, int y, int z)
{
delete[] grid; //make sure no memory leaks since grid might have already been allocated
nx = x;
ny = y;
nz = z;
grid = new double[nx*ny*nz];
}
};
After the construction, just call the method init:
Plot p();
p.init(2,3,4);
EDIT:
You should however consider Mark B's answer. I would also use something from std:: rather than a dynamically allocated array. Much easier to manage.
EDIT2:
As per Constantinius' answer, avoid init() methods when you can. If you specifically need the initalization AFTER construction, use it, otherwise keep all initialization logic in the constructor.
It depends on how your Plot class should be used. If you consider it necessary to create objects of this class only with valid sizes you should not allow a default constructor. You do this by defining your own constructor like that:
public:
Plot(int _nx, int _ny, int _nz) : nx(_nx), ny(_ny), nz(_nz)
{
// initialize your array
grid = new double[nx*ny*nz];
}
also don't forget your destructor to clear the allocated memory:
~Plot()
{
delete[] grid;
}
class Plot {
int nx; // number of "x" values
int ny; // number of "y" values
int nz; // number of "z" values
double* grid; // one dimensional array which stores nx*ny*nz values
double tgrid(int ix, int iy, int iz); // function which searches grid and returns value
public:
/* default constructor */
Plot() : nx(0), ny(0), nz(0), grid(NULL) { }
/* rule of five copy constructor */
Plot(const Plot& b) : nx(b.nx), ny(b.ny), nz(b.nz) {
int max = nx*ny*nz;
if (max) {
grid = new double(max);
for(int i=0; i<max; ++i)
grid[i] = b.grid[i];
} else
grid = NULL;
}
/* rule of five move constructor */
Plot(Plot&& b) : nx(b.nx), ny(b.ny), nz(b.nz) grid(b.grid) { b.grid = NULL; }
/* load constructor */
Plot(std::istream& b) : nx(0), ny(0), nz(0), grid(NULL) { Load(b); }
/* rule of five destructor */
~Plot() { delete[] grid; }
/* rule of five assignment operator */
Plot& operator=(const Plot& b) {
int max = b.nx*b.ny*b.nz;
double* t = new double[max];
for(int i=0; i<max; ++i)
t[i] = b.grid[i];
//all exceptions above this line, NOW we can alter members
nx = b.nx;
ny = b.ny;
nz = b.nz;
delete [] grid;
grid = t;
}
/* rule of five move operator */
Plot& operator=(Plot&& b) {
nx = b.nx;
ny = b.ny;
nz = b.nz;
delete [] grid;
grid = b.grid;
b.grid = NULL;
}
/* always a good idea for rule of five objects */
void swap(const Plot& b) {
std::swap(nx, b.nx);
std::swap(ny, b.ny);
std::swap(nz, b.nz);
std::swap(grid, b.grid);
}
/* your load member */
void Load(std::istream& in) {
//load data
//all exceptions above this line, NOW we can alter members
//alter members
};
};
int main() {
Plot x; //default constructor allocates no memory
Plot y(x); //allocates no memory, because x has no memory
Plot z(std::cin); //loads from stream, allocates memory
x = z; //x.grid is _now_ given a value besides NULL.
}
This answers your questions I think. Still: use a std::vector.

What's the proper way to pass a pointer to a function for deletion?

I have a matrix declared like int **matrix, and I know that the proper way to pass it to a function to allocate memory should be like this:
void AllocMat(int ***mat, int size);
But now I need to delete these memory in another function and am not sure about what to pass:
void DeallocMat(int **mat, int size);
or
void DeallocMat(int ***mat, int size);
I think the second one should be right, but neither way gives me segmentation fault as I tried.
The question is tagged C++, and yet the answers only use the C subset...
Well, first of all, I would recommend against the whole thing. Create a class that encapsulates your matrix and allocate it in a single block, offer operator()(int,int) to gain access to the elements...
But back to the problem. In C++ you should use references rather than pointers to allow the function to change the argument, so your original allocate signature should be:
void AllocMat(int **&mat, int size);
And call it like:
int **matrix = 0;
AllocMat( matrix, 5 );
Or better, just return the pointer:
int **AllocMat( int size );
int **matrix = AllocMat( 5 );
For the deallocation function, since you don't need to modify the outer pointer, you can just use:
void DeallocMat( int**mat, int size ); // size might be required to release the
// internal pointers
Now, for a sketch of the C++ solution:
template <typename T> // no need to limit this to int
class square_matrix {
const unsigned size;
T * data;
public:
square_matrix( unsigned size ) : size(size), data( new T[size*size]() ) {}
square_matrix( matrix const & m ) : size( m.size ), data( new T[m.size*m.size] ) {
std::copy( m.data, m.data+size*size, data );
}
~matrix() {
delete [] data;
}
T const & operator()( unsigned x, unsigned y ) const {
// optional range check and throw exception
return data[ x + y*size ];
}
void set( unsigned x, unsigned y, T const & value ) {
// optional range check and throw exception
data[ x + y*size ] = value;
}
};
First is correct. But your real problem is that you are using pointers when there are better alternatives. For a 2d matrix you should use a vector of vectors
#include <vector>
typedef std::vector<std::vector<int> > Matrix;
Matix m;
Now there is no need to delete anything, so one less thing to go wrong.
void DeallocMat(int **mat, int size) - allows you to deallocate memory (since you have passed the value of mat only allowing to deallocate memory but not change mat)
void DeallocMat(int ***mat, int size) - allows you to deallocate memory and change the value of mat to NULL (since you have now passed a pointer to mat allowing you to change its value)
The extra "*" just handles the pointer to be behaved as call by reference. If you want to get the output from your function, you need an extra "*" in your declaration. In this case, you should pass the reference of your pointer (using &) to these functions.
The reason why you required to pass a pointer to double pointer because your local variable must required to reflect with the new updated memory
void Foo(int * a)
{
a = new int[10];
}
int main()
{
int *a = 0;
Foo( a );
}
Now the memory will be allocated but the pointer A will not be update because the value of pointer A is simply copied to another pointer variable which is parameter of Foo. Once the Foo is returned, a will remain 0. To make it refect that, you should write code like follows
void Foo(int ** a)
{
*a = new int[10];
}
int main()
{
int *a = 0;
Foo( &a );
}
Here you're passing the address of a pointer. The which means that, the value which contains in the pointer will be updated from the Foo function.You can debug through and see how it works.
If you're sure that you will not access the pointer anymore, please use the first type. Otherwise use the second one. Make sure that you set the pointer to NULL to avoid further memory corruptions or dangling pointers.
The thing that confuses me about your question is that most people would not declare a matrix as an int **. The reason for this is that you would be forced to then allocate it in a loop. Your allocation function would require two parameters, which are the dimensions of the array like this:
void AllocMat(int *** mat, int n, int m) {
int ** result = new int * [ n ];
for (int x=0; x<n; x++) {
result[x] = new int [ m ];
}
*mat = result;
}
If this were the case, the corresponding deallocation function would require knowledge of the size of n as follows:
void DeallocMat(int *** mat, int n) {
if (mat == NULL || *mat == NULL) return;
int ** tmp = *mat;
for (int x=0; x<n; x++) {
if (tmp[x] != NULL) delete [] tmp[x];
}
delete [] tmp;
*mat = NULL;
}
With this approach, you could access your matrix like this:
int ** mat = NULL;
AllocMat(&mat, n, m);
for (int x=0; x<n; x++) {
for (int y=0; y<m; y++) {
mat[x][y] = 1;
}
}
DeallocMat(&mat, n);
Usually, people allocate matrices as a single buffer of memory to avoid extra allocations and pointer indirections, which is how I recommend you do it. In that case, you allocation function would look like this:
void AllocMat2(int ** mat, int n, int m) {
*mat = new int [ n * m ];
}
And the corresponding deallocation function like this:
void DeallocMat2(int ** mat) {
if (mat != NULL && *mat != NULL) {
delete [] *mat;
*mat = NULL;
}
}
And you would access it follows:
int * mat2 = NULL;
AllocMat2(&mat2, n, m);
for (int x=0; x<n; x++) {
for (int y=0; y<m; y++) {
mat2[x * n + y] = 1;
}
}
DeallocMat2(&mat2);
Either way works, but if you pass a pointer to the pointer you need to dereference it first. And the size parameter is redundant.
void DeallocMat(int **mat)
{
delete[] mat;
}
void DeallocMat(int ***mat)
{
delete[] *mat;
*mat = NULL;
}