I am fairly new to using pointers in C++ but I will try and explain what I want to do.
I have a class object Rx (receiver), and in my program I will be using multiple receivers at the same time. Each receiver has a vector of data (observations), for simplicity I am just using a vector of doubles. I also have an array of bools that determine which observations to use and I would like each receiver (as a member variable) have a pointer to this array. For example the first element in the array of bools will say "true or false use the first observation you have receiver".
Also, further in my code I would also like to point to an array of objects, would I follow the same procedure?
int main()
{
// The elements in this array are set in the code before
bool use_observations[100];
// I have chosen 3 for an example but in my actual code I have a vector
// of receivers since the quantity varies
Rx receiver_1, receiver_2, receiver_3;
// I would like to set the pointer in each receiver to point
// to the array use_observations
receiver_1.SetPointer(use_observations);
receiver_2.SetPointer(use_observations);
receiver_3.SetPointer(use_observations);
} // end of main()
My receiver class declarations and definitions:
class Rx{
public:
Rx(); // Constructor
Rx(const Rx& in_Rx); // Copy constructor
~Rx(); // Destructor
void SetPointer(bool* in_Array); // Function to set pointer to use_observation
private:
std::vector<double> data;
bool* pointer_to_array[10];
}; // end of class Rx
void Rx::SetPointer(bool* in_Array)`{*pointer_to_array`= in_Array);
This is where I get the problems, either it doesnt assign correctly (get lots of nulls or not assigned) or I get an error on pointer_to_array saying expression must be a modifiable value
I haven't bothered showing the constructor, copy constructor and Destructor. I know normally in the destructor you should delete the pointer however Rx does not own the data in the array so I do not want to delete it.
Thanks for your help
EDIT** I have shown some code that I am using and what I get for results and I have modified SetPointer() to display some results
int main
{
bool use_observations [6] = {true, true, true, true, true, true};
Rx receiver_1;
receiver_1.SetPointer(use_observations);
}
void Rx::SetPointer(bool* in_Array)
{
*pointer_to_array = in_Array;
for(int i = 0; i < 6; i++)
{
if(*pointer_to_array[i] == true)
std::cout << "Good" << std::endl;
} // end of for loop
} // end of SetPointer()
When I debug and step over (*pointer_to_array = in_Array) I get the result
{true, and 0xCCCCCCCC for the rest of the elements} and then on the second iteration of the for loop it crashes saying "Access violation reading location 0xCCCCCCCC
SECOND EDIT **
Thank you everyone for your help. #PaulMcKenzie pointed out in his implementation (in the comments) in Rx that I should have bool* pointer_to_array not bool* pointer_to_array[6] and that solved the issue. As well I should be pointing to the start of the array buffer, not a pointer to the array.
The issue is that you want a pointer to the start of the array buffer, not a pointer to the array.
class Rx{
public:
void SetPointer(bool* in_Array);
bool* pointer_to_array;
};
void Rx::SetPointer(bool* in_Array) {pointer_to_array = in_Array);
Note the removal of the *.
Related
I'm trying to realize two methds append() and clear().
In appened(), I need to newPoint to the end of a list. If the list is empty, then adds newPoint as the first(and only) point in the list.
In clear(),I need to remove all the points in a list.
Can you give me some advice to realize appened and clear.
Here is a code:
//
#pragma once
const int maxListSize = 10;
class Point
{
private:
float x;
float y;
public:
Point(float x0 = 0, float y0 = 0)
{
x = x0;
y = y0;
}
};
class PointList
{
private:
//Data members
int size;
int cursor;
Point points[maxListSize];
public:
PointList();
//List Manipalution operations
void append(Point newPoint);
void clear();
~PointList();
};
*I don't need you to write everything for me, just give me some advice. I would like to realize it by myself. Thank you for helping.
Since you store your list elements by value (Point points[maxListSize]),
it is quite easy to do:
PointList() :size(0) {}
void append(Point newPoint) { points[size++] = newPoint; }
void clear() { size = 0; }
This assumes that your Point object doesn't manage any resource, which is true for this particular example. Otherwise, inserted Point objects should be destroyed in clear.
To get the semantics that you're probably expecting for appending new items, and clearing out existing items, I suggest you look at the placement new operator, and manually calling the destructor of an item in the list.
Currently your class will construct all of the items in the list when you create the list. This can be quite time consuming for complex structures. Then, instead of the constructor for your elements being called, you'll instead be calling the copy-assignment operator, as the items are already constructed.
If you store your array as
char * points[sizeof(Point)*maxListSize];
Any only initialize the items when they're actually added, you avoid the construction cost when you create the list.
Your append function takes it's argument by value. Instead, I recommend you have two append functions. One that takes const&, and the other that takes an rvalue-reference. Then, inside the append function, call the placement new operator on the address of the next location in your array.
To clear the array, simple call the destructor for each element in the array one at a time.
I'm using MFC C++ for my Windows Application, where I need to persist (not in a Database) some data using CMapPtrToPtr. The key is a pointer to a structure (let's call it SIGNAL_DATA* pSignal) and the value is a double array.
The problem is, when I read the value again, it is giving me a garbage/undefined value (not the value I stored).
Sample Code:
In the header file:
CMapPtrToPtr prevZoomValsMap;
double zoomPreVals[2];
In the implementation class:
void funktion1()
{
if(ersteSchleife == FALSE) //first time, it is false
{
SIGNAL_DATA* pSelectedSignal; //properly initialised. verified in debug mode
zoomPreVals[0] = zoomMinSkal; //valid double values. verified in debug mode
zoomPreVals[1] = zoomMaxSkal;
prevZoomVals.SetAt((void*) pSelectedSignal, (void*) zoomPreVals);
ersteSchleife = TRUE;
}
else
{
funktion2();
}
}
In another function, when I read the value as below, I'm getting garbage values.
void funktion2()
{
void *zoomValuesTemp_;
prevZoomValsMap.Lookup((void*) sigTemp, zoomValuesTemp_);
double *zoomValuesTemp = (double*)zoomValuesTemp_;
if(zoomValuesTemp == NULL) //verified in debug mode. never becomes NULL.
{
int aRTD = 10; //dummy assignment.
}
double aValue = zoomValuesTemp[0] ; //Access Violation
}
Assuming that the code you provide is running in a function, we get
void store_it(SIGNAL_DATA* pSelectedSignal)
{
double zoomPreVals[2] = {zoomMinSkal, zoomMaxSkal}; //also, initialised.
prevZoomVals.SetAt((void*) pSelectedSignal, (void*) zoomPreVals);
}
If this is what you have, then you are storing the address of a local variable (zoomPreVals) in the map. Since zoomPreVals is destroyed at the end of the function, the pointer to zoomPreVals becomes invalid. You cannot use this pointer anymore.
You must make sure that the pointer stays valid, so you can for example allocate a new structure with new and store the pointer in the map - don't forget to free the data later.
You might also consider using CMap<SIGNAL_DATA*, SIGNAL_DATA*, MYDATA, MYDATA&> and store objects instead of pointers as map values.
You might also consider using STL classes like map and unique_ptr.
Your retrieval code is not correct. You should not cast to match the function parameters, but pass the right parameters.
void *zoomValuesTemp_;
prevZoomVals.Lookup((void*) sigTemp, zoomValuesTemp_);
double *zoomValuesTemp = (double*)zoomValuesTemp_;
I am trying to write a program that will solve a maze using a class and a tree. I am trying to use a class to represent the maze (the design will be entered using cin), and the class contains a struct as a private member.
This struct contains two ints (for the x and y coordinate of the position) and an array with 3 spaces that will hold three pointers to other structs.
In the constructor function for my class, I am trying to set all the pointers in the array to NULL to start off. The program compiles fine, but when I get to the constructor the program gives me a segmentation fault. Here is some relevant code:
const int POSSIBLE_BRANCHES = 3; //at any point the path can split in 3 ways
struct PathNode
{
int x_coord;
int y_coord;
PathList branches[POSSIBLE_BRANCHES];
};
typedef PathNode *PathList;
class Maze
{
private:
PathList initial_pos;
public:
Maze();
};
And the constructor:
Maze::Maze()
{
cout << "entered constructor" << endl;
for (int i = 0; i < POSSIBLE_BRANCHES; i++)
{
initial_pos->branches[i] = NULL;
}
}
I get the "entered constructor" phrase printed out, but the program stops immediately afterwards. I am assuming it is some silly problem with my pointer syntax, but I have been unable to locate the problem.
As I understand it: the -> operator dereferences the pointer to the PathNode struct, so now we have access to the members like x_coord, y_coord, and branches. The [] operator gets to each index of the branches array. And because it is an array of pointers to PathNodes, setting them as NULL should be fine. Where is the flaw in my reasoning?
Edit:
Solved. See the answer marked as best.
You haven't yet allocated initial_pos before you use it. That is causing the segfault.
Something along the lines of:
Maze::Maze()
: initial_pos(new PathNode)
{
cout << "entered constructor" << endl;
for (int i = 0; i < POSSIBLE_BRANCHES; i++)
{
initial_pos->branches[i] = NULL;
}
}
Should fix your problem.
Your constructor is the first thing that gets called for the new class, so you never allocate or initialize initial_pos in anyway, but you then dereference it - leading to undefined behavior (most likely causing a segfault)
I'm compiling using Code::Blocks on Windows 7 using the MinGW compiler (which I can only assume is the latest version; both Code::Blocks and MinGW were installed this past week). My issue crops up under a particular circumstance, and my attempts to write a simpler script that demonstrates the problem have failed (which implies that there is something wrong with my structure). Also, my apologies for how long this post is.
Currently, I'm rolling with one class, FXSDL, which will act as an SDL wrapper:
class FXSDL
{
public:
FXSDL();
virtual ~FXSDL();
int Initialize();
int Render();
FXID CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims);
int SetAnim(FXID hRefID, FXID hAnimID);
FXID hPlayer;
protected:
private:
list<FXSurface> m_lstFXObjects;
list<FXSurface>::iterator m_liFirst;
SDL_Surface* m_lpsfSDLScreen;
Uint32 m_tmOld;
Uint32 m_tmFrame;
};
The value type of my list is:
struct FXSurface
{
FXID hRefID;
int wpxTile;
int hpxTile;
int wpxTotal;
int hpxTotal;
int cntTiles;
map<int, vector<int> > htAnims; // All animations
map<int, vector<int> >::iterator vCurr; // Currently active animation
vector<int>::iterator fiCurr; // Currently active frame
SDL_Surface* lpsfSDL;
SDL_Rect* lprcTiles; // Predefined frame positions
string* fpImage;
};
I've implemented very simple initialize and render function. The CreateCharacter function takes a few parameters, the most important of which is htAnims, a map of integer vectors (idea being: I define numeric ids with easy-to-remember representations, such as FXA_IDLE or FXA_WALK, as the key, and the series of number values representing frames for the animation as a vector). This could be fairly easily implemented as a multidimensional integer array, but animations are variable in length and I want to be able to add new anims (or redefine existing ones) without having to recast an array.
The CreateCharacter function is simple. It creates a new FXSurface, populates it with the required data, and pushes the new FXSurface onto the list:
FXID FXSDL::CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims)
{
//list<FXSurface>::iterator lpsfTemp;
FXSurface lpsfTemp;
list<FXSurface>::iterator lpsfPos;
SDL_Rect* lprcCurr = NULL;
int cntTileW = 0;
int cntTileH = 0;
int cntCurr = 0;
// Start off by initializing our container struct
//lpsfTemp = new FXSurface();
lpsfTemp.lpsfSDL = IMG_Load(fpImage.c_str()); // Try to load the requested image
if(lpsfTemp.lpsfSDL != NULL) // If we didn't fail to
{
// Assign some variables for tracking
lpsfTemp.hRefID = hRefID;
lpsfTemp.fpImage = &fpImage;
lpsfTemp.wpxTotal = lpsfTemp.lpsfSDL->w;
lpsfTemp.hpxTotal = lpsfTemp.lpsfSDL->h;
// If a tile width was specified, use it
if(wpxTile != 0)
{
lpsfTemp.wpxTile = wpxTile;
lpsfTemp.hpxTile = hpxTile;
} // Otherwise, assume one tile
else
{
lpsfTemp.wpxTile = lpsfTemp.wpxTotal;
lpsfTemp.hpxTile = lpsfTemp.hpxTotal;
}
// Determine the tiles per row and column for later
cntTileW = lpsfTemp.wpxTotal / lpsfTemp.wpxTile;
cntTileH = lpsfTemp.hpxTotal / lpsfTemp.hpxTile;
// And the total number of tiles
lpsfTemp.cntTiles = cntTileW * cntTileH;
lpsfTemp.lprcTiles = new SDL_Rect[cntTileW*cntTileH];
// So we don't calculate this every time, determine each frame's coordinates and store them
for(int h = 0; h < cntTileH; h++)
{
for(int w = 0; w < cntTileW; w++)
{
cntCurr = (h*cntTileW)+w;
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
}
}
// Now acquire our list of animations and set the default
//lpsfTemp.htAnims = new map<int, vector<int> >(*htAnims);
lpsfTemp.htAnims = htAnims;
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
this->m_lstFXObjects.push_back(lpsfTemp);
}
else
{
hRefID = 0;
}
return hRefID;
}
It is precisely as the object is pushed that the error occurs. I've stepped through the code numerous times. Initially, I was only able to tell that my iterators were unable to dereference to the FXSurface object. After using watches to identify the exact memory address that the iterator and list objects pointed to, and dereferencing the address, I noticed the reason for my segfaults: all the values which I put into the original FXSurface were pushed down two memory blocks when the list object copied it!
My process for doing this is simple. I set up a breakpoint at the return statement for CreateCharacter, which gives me a view of lpsfTemp (the FXSurface I later add to the list) and m_lstFXObjects (the list I add it to). I scroll through the members of m_lstFXObjects, which brings me to _M_node, which contains the memory address of the only object I have added so far. I add a watch to this address in the form of (FXSurface)-hex address here-
First, find the address:
(There should be a picture here showing the highlighted _M_node attribute containing the list item's address, but I can't post pictures, and I can only post one URL. The second one is by far more important. It's located at http://www.fauxsoup.net/so/address.jpg)
Next, we cast and deference the address. This image shows both lpsfTemp and the copy in m_lstFXObjects; notice the discrepancy?
http://www.fauxsoup.net/so/dereferenced.jpg - See? All the values are in the correct order, just offset by two listings
I had initially been storing fpImages as a char*, so I thought that may have been throwing things off, but now it's just a pointer and the problem persists. Perhaps this is due to the map<int, vector<int> > I store?
FXSDL has a destructor, but no copy constructor and no assignment operator. Yo you're using naked pointers, but violate the Rule of Three.
I'm not going to look any further.
Use smart pointers to manage resources. Do not put a naked resource into a type, except when that type's only intention is to manage this one resource. From another answer given yesterday:
As a rule of thumb: If you have to manually manage resources, wrap each into its own object.
At a glance, I'd say you're double-deleting lpsfSDL and/or lprcTiles. When you have raw pointers in your structure, you need to follow the rule-of-three (implement copy constructor, assignment operator, and destructor) to properly manage the memory.
These lines look wrong to me:
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
lpsfTemp.lprcTiles is a SDL_Rect*. lprcTemp.lprcTiles[cntCurr] is a SDL_Rect. You should be writing this, IMHO:
SDL_Rect tmpRect;
tmpRect.w = lpsfTemp.wpxTile;
tmpRect.h = lpsfTemp.hpxTile;
tmpRect.x = w*lpsfTemp.wpxTile;
tmpRect.y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = tmpRect;
Dump the lprcCurr entirely.
Now this code:
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
This is bad. These iterators are invalid as soon as the push_back completes. That push_back is making a copy of lpsfTemp. The map and vector members are going to copy themselves and those iterators will copy themselves but they will be pointing to lpsfTemp's members which are going to be destroyed as soon as CreateCharacter exits.
One way to fix that would be to push_back a FXSurface object at the beginning, use back() to get its reference and operate on that instead of lpsfTemp. Then the iterators would stay consistent and they should stay consistent since you are using a list which does not copy its objects around. If you were using a vector or deque or anything other than a list you would need to manage all those pointers and iterators in the copy constructor and assignment operator.
Another thing: Double and triple check your array bounds when you access that lprcTiles array. Any mistake there and you could be scribbling over who knows what.
I don't know if any of that will help you.
I'm having an issue where using vector.push_back(value) is overwriting the final value, rather than appending to the end. Why might this happen? I have a sample item in the vector, so it's size never hits zero. Below is the code..
void UpdateTable(vector<MyStruct> *Individuals, MyStruct entry)
{
MyStruct someEntry;
bool isNewEntry = true;
for (int i = 0; i < Individuals->size(); i++)
{
if (!(strcmp(Individuals->at(i).sourceAddress, entry.sourceAddress)))
{
isNewEntry = false;
//snip. some work done here.
}
}
if(isNewEntry)
{
Individuals->push_back(entry);
}
}
This let's my first "sample" value stay in, and will allow for just one more item in the vector. When 2 new entries are added, the second overwrites the first, so the size is never larger than 2.
edit: More code, since this is apparently not the issue?
void *TableManagement(void *arg)
{
//NDP table to store discovered devices.
//Filled with a row of sample data.
vector<MyStruct> discoveryTable;
MyStruct sample;
sample.sourceAddress = "Sample";
sample.lastSeen = -1;
sample.beaconReceived = 1;
discoveryTable.push_back(sample);
srand(time(NULL));
while(1)
{
int sleepTime = rand() % 3;
sleep(sleepTime);
MyStruct newDiscovery = ReceivedValue();
if (newDiscovery.lastSeen != -1000) //no new value from receivedValue()
{
UpdateTable(&discoveryTable, newDiscovery);
}
printTable(&discoveryTable);
}
return NULL;
}
I'm going to hazard a guess:
Suppose MyStruct is declared like
struct MyStruct
{
const char *sourceAddress;
// Other Gubbins ...
};
And that ReceivedValue does something like
MyStruct ReceivedValue()
{
static char nameBuffer[MAX_NAME_LEN];
// Do some work to get the value, put the name in the buffer
MyStruct s;
s.sourceAddress = nameBuffer;
// Fill out the rest of MyStruct
return s;
}
Now, every structure you push into your vector has sourceAddress pointing to the same global buffer, every time you call ReceivedValue it overwrites that buffer with the new string - so every entry in your vector ends up with the same string.
I can't be sure without seeing the rest of your code, but I can be sure that if you follow some of the good C++ style suggestions in the comments to your question this possiblity would go away.
Edit for clarification: there's no need to heap allocate your structures, simply declaring sourceAddress as a std::string would be sufficient to eliminate this possibility.
The scope for the items you are pushing into the database is expiring. They're being destructed when you leave the {} in which they were created - and as such the reference to them is no longer valid.
You need to change it from vector<MyStruct> to vector<MyStruct*> (preferably using safe pointers from Boost:: instead of pointers, but you get the idea).
You are creating the item within the (limited) scope and pushing it onto the vector (while the struct is copied, the strings in it are not!) it then reuses the same memory location (most likely if properly optimized) to store the next "new" struct and the one after that and so on and so forth.
Instead, within the limited scope create MyStruct *myObject = new MyStruct and assign its values, then push the pointer to the vector.
Remember to delete all values from the vector before clearing it/destroying it!!
Or, of course, you could use std::string/CString/whatever instead of a char array and avoid the issue entirely by having a safe-to-copy struct.
ComputerGuru's answer works however there in another alternative. You can create a copy constructor and overload operator= for MyStruct. In these operations, you need to copy the actual string into the new struct. In C++, structs are nothing more than classes with default public access instead of default private access. Another alternative is to use std::string instead of char* for the string value. C++ strings already have this behavior.
struct MyStruct {
std::string sourceAddress;
int lastSeen;
int beaconReceived;
};
Seems odd to me: Maybe there is something wrong with the //snip part of the code?
Try to log the size of the vector before and after the push_back call (either in the debugger or using cout) and also have a look at the isNewEntry variable.
Your code looks alright to me. Is it possible that you are not passing the right vector in? What I mean is that the behaviour you describe would appear if somehow your Individuals vector is being reset to its orginal 1-entry state before you tried to add the 3rd entry, then it would appear as if your 2nd entry was being overwritten.
Here is what I mean:
int test_table()
{
string SampleAddresses[] = {"Sample Address 1", "Sample Address 2"};
for (int i = 0; i < 2; i++)
{
// All this work to build the table *should* be done outside the loop; but we've accidentally put it inside
// So the 2nd time around we will destroy all the work we did the 1st time
vector<MyStruct> Individuals;
MyStruct Sample;
Sample.sourceAddress = "Sample Address 0";
Test.push_back(Sample);
// this is all we meant to have in the loop
MyStruct NewEntry;
NewEntry.sourceAddress = SampleAddresses[i];
UpdateTable(Individuals, NewEntry);
}
//Now the table has 2 entries - Sample Address 0 and Sample Address 2.
}
If this was all your code then the problem would be obvious. But it might be concealed in some other pieces of code.