i am running into a segfault in my c++ program and can't figure out my mistake.
I have a class Map which is a 2D-vector of objects of the class MapCells. The task is to go from cell to cell. From each cell, there are two possible ways to other cells. Maybe some 'pseudo' code can explain it better:
//map.h
class MapCell {
private:
MapCell *p_way1_, *p_way2_;
int some_information_;
public:
MapCell* getWayPointer1();
MapCell* getWayPointer2();
int getInformation();
void setWayPointer1(MapCell* new_p_way1);
void setWayPointer1(MapCell* new_p_way2);
};
class Map {
private:
std::vector< std::vector<MapCell> > map_;
public:
void initializeMap();
MapCell* getStartPointer();
};
int main()
{
Map map;
map.initializeMap();
MapCell *p_current_cell, *p_next_cell;
p_current_cell = map.getStartPointer();
while(p_current_cell->getInformation() != 0)
{
if(p_current_cell->getInformation() == 1)
{
p_next_cell = p_current_cell->getWayPointer1();
}
else
{
p_next_cell = p_current_cell->getWayPointer2();
}
p_current_cell = p_next_cell;
}
return 0;
}
This is only a little part of the real code. But i think i made a fundamental mistake so i hope this is enough code to fix it.
The problem is, that my code runs for minutes without problems and suddenly i get a segfault. gdb states, that the segfault happens when getInformation() is called. I also found out, that at some point all p_way2_ vectors lead to nonsense. Can you help me?
Thank you very much in advance!
Problem in lines
MapCell* p_current_cell, p_next_cell;
MapCell* p_way1_, p_way2;
Second parameter is not pointer and MapCell is implicit convert from pointers (or you will get multiple compile-times errors).
Try change to
MapCell* p_current_cell, *p_next_cell;
MapCell* p_way1_, *p_way2;
Related
This is in relation to an earlier question I had. I haven't managed to solve the problem there but for now I'm just trying to get better acquainted with the code to figure out how to deal with that problem.
Towards that goal, I've got around to trying out the suggestions given in that question and I'm a little stumped as to why the following isn't working.
in the header I have
class A {
public:
typedef std::multimap<int, double> intdoublemap_t;
const intdoublemap_t& getMap() const;
void setkey(int k);
void setvalue(double v);
void insertIntoMap();
intdoublemap_t mMapA;
private:
int key;
double value;
};
class B {
public:
typedef std::multimap<int, double> intdoublemap_t;
void mapValues(const A& a);
private:
intdoublemap_t mMapB;
};
in the implementation I have
const A::intdoublemap_t& A::getMap() const { return mMapA; }
void A::setkey(int k) { key = k; }
void A::setvalue(double v) { value = v; }
void A::insertIntoMap(){mMapA.insert(std::make_pair(key, value));}
void B::mapValues(const A & a){ const A::intdoublemap_t& mref = a.getMap();
mMapB = mref; }
and in main()
A a;
a.setkey(10);
a.setvalue(1232.2);
a.insertIntoMap();
B b;
b.mapValues(a);
The code compiles fine and everything to do with a works as expected but the map is not passing to b at all. It stays empty
Can anyone tell me why?
edit: I took another look at this and saw how to do it. I knew it was something stupidly basic. I just had to set mref in the function to a map in B and then could call a function to work on that map within B.
As #FrancoisAndrieux notes, your getMap() only sets a reference local to the function - not the class' intdoublemap_t mref. If you want the latter to be a reference to a map elsewhere, you have three options:
Make it intdoublemap_t& mref, initialize it on construction of the B instance.
Make it std::reference_wrapper<intdoublemap_t> mref, set it whenever you want (e.g. in mapValues().
Make it intdoublemap_t* (or std::shared_ptr<intdoublemap_t> in both A and B), set it whenever you like.
Note: As #FrancoisAndrieux says in a comment, with the second and third option (and without std::shared_ptr) you will have to be careful not to allow the reference to be used after the original object's lifetime has expired.
Having said all the above - I must also say that your design seems rather off to me. You should really not be doing any of these things and I'm 99% sure you're approaching your task the wrong way.
Reverting this back to the original question. Going to post the more detailed question as a new question. Thanks everyone for the help and advice of avoiding the new. Having trouble passing around instances of objects in this question.
class dogClass {
public:
void setVariableA(std::vector<double> newNum) {
variableA.push_back(newNum);
}
dogClass &dogClass::operator=(const dogClass &src) {
variableA = src.variableA;
return *this;
}
private:
std::vector<std::vector<double>> variableA;
};
class animalClass {
public:
void getDogOne(dogClass &dogOne) {
dogOne = dogs[0];
}
void setDogOne(dogClass dogOne) {
dogs.push_back(dogOne);
}
private:
std::vector<dogClass> dogs;
};
int main() {
animalClass* iAnimalClass = new animalClass();
dogClass* iDogClassOne= new dogClass();
iAnimalClass->setDogOne(iDogClassOne);
std::vector<double> newNum;
newNum.push_back(12);
newNum.push_back(15);
iDogClassOne->setVariableA(newNum);
dogClass iDogClassTwo;
iAnimalClass->getDogOne(iDogClassTwo);
//Why are iDogClassOne and iDogClassTwo not equal.
return 0;
}
There are a couple of issues.
you don't have a copy constructor for your dog class as you have indicated in your title. what you have done is overloaded the = operator.
you are trying to pass iDogClassOne as pointer to the animalClass:: setDogOne() but animalclass::setDogOne receives the arguments by value, not as reference or pointer.
you can use the dereference operator*iDogClassOne. this pretty much telling the compiler you want to pass the object which the iDogClassOne is pointing at.
dogClass* iDogClassOne = new dogClass();
iAnimalClass->setDogOne(*iDogClassOne);
or a better way of doing, you can completly remove the heap allocation
dogClass dogobj;
iAnimalClass->setDogOne(dogobj);
same problem as described in (2). but this time your animalclass::getDogOne receives the arguments by a reference.this again can be easly fixed by modifying the getdogone or/and by passing a pointer. i will leave this as it is. if you still need a help let me know in comments and will edit it further. but i encourage you to try to give it a go first.
you are missing semicolon (;) at the end of class declarations
I have a relatively simple question but I cant seem to find an answer specific for my case and I just may not be approaching this problem the right way. I have a class that looks like this:
struct tileProperties
{
int x;
int y;
};
class LoadMap
{
private:
ALLEGRO_BITMAP *mapToLoad[10][10];
tileProperties *individualMapTile[100];
public:
//Get the struct of tile properties
tileProperties *getMapTiles();
};
I have an implementation that looks like this for the getter function:
tileProperties *LoadMap::getMapTiles()
{
return individualMapTile[0];
}
I have code in the LoadMap class that will assign 100 tile properties for each struct in the array. I want to be able to access this array of structs in my main.cpp file but I just cant seem to find the right syntax or approach. My main.cpp looks like this.
struct TestStruct
{
int x;
int y;
};
int main()
{
LoadMap _loadMap;
TestStruct *_testStruct[100];
//This assignment will not work, is there
//a better way?
_testStruct = _loadMap.getMapTiles();
return 0;
}
I realize that there are many approaches to this, but I'm trying to keep this implementation as private as possible. If someone could please point me in the right direction I would greatly appreciate it. Thank you!
TestStruct *_testStruct;
_testStruct = _loadMap.getMapTiles();
This will get you a pointer to the first element in the array returned. You can then iterate through the other 99.
I would highly recommend using vectors, or another container, and writing getters that don't return pointers to bare arrays like that.
First of all, here, why do we need TestStruct, you can use "tileProperties" structure itself...
And imp thing,
tileProperties *individualMapTile[100]; is array of pointers to the structure.
Hence, individualMapTile will have pointers in it.
You have returned the first pointer, hence you can access the first structure only. What about the others????
tileProperties** LoadMap::getMapTiles()
{
return individualMapTile;
}
int main()
{
LoadMap _loadMap;
tileProperties **_tileProperties;
_tileProperties = _loadMap.getMapTiles();
for (int i=0; i<100;i++)
{
printf("\n%d", (**_tileProperties).x);
_tileProperties;
}
return 0;
}
Use vectors instead of arrays where possible. Also consider an array/vector of TestStruct directly rather than pointers to them. I can't tell if that would be appropriate for you from your code sample.
class LoadMap
{
public:
typedef vector<tileProperties *> MapTileContainer;
LoadMap()
: individualMapTile(100) // size 100
{
// populate vector..
}
//Get the struct of tile properties
const MapTileContainer& getMapTiles() const
{
return individualMapTile;
}
MapTileContainer& getMapTiles()
{
return individualMapTile;
}
private:
MapTileContainer individualMapTile;
};
int main()
{
LoadMap _loadMap;
LoadMap::MapTileContainer& _testStruct = _loadMap.getMapTiles();
}
EDITED BELOW FOR UPDATES!!!
Thank you for the help, please by all means point out ALL mistakes , I don't care if it sounds rude or mean or whatever, emo junk. Just give it to me straight so I can understand what is going wrong.
Hi everyone!
I am a rookie C++ programmer trying to learn and gain some IRL exp for C++.
I am attempting the following inside my VC++ (vs2008) compiler:
typedef unsigned short USHORT;
class Grid
{
...
public:
Grid()
{
Tile[36]* tileList_ptr;
}
...
};
In essence, I want to put 36 tiles , slam them into an array nice and tidy on the heap for a 8x8 playfield that never changes in size. Like a chessboard. Refer to them with a pointer, and fiddle with them in the related cpp file if needed.
If you aren't laughing by now at this attempt then I probably made a syntax error instead of major design flaw :P
Any help would be much appreciated!
Thanks in advance
EDIT 24/08/2010 13:49 (Time of start)
My code is now as following example:
The Grid Header file Grid.h:
#include "Tile.h"
class Grid
{
//no more typedef used
public:
Tile grid[8][8];
private:
unsigned short selectedItemIndexValue;
public:
Grid()
{
Initialize();
}
~Grid(){}
void Update();
void FinalizeMove(unsigned short index);
void Draw();
private:
void Initialize(); //Initializes members
};
The Grid.cpp file:
#include "stdafx.h"
#include "Grid.h"
//Not tile , that used to give me a class redefinition error
unsigned short selectedItemIndexValue;
//No more typedef used
void Grid::Update()
{
//Respond to controller commands
}
void Grid::FinalizeMove(unsigned short index)
{
}
void Grid::Draw()
{
}
void Grid::Initialize()
{
for(int i = 0; i < 4; i++)
{
Grid::grid[i] = new Tile::Tile(10,10); // ATTEMPT AT FILLING ARRAY
}
}
Tile.h file
class Tile
{
public:
private:
enum TileOccupation
{
EmptyTile = 0,
WhiteSphere = 1,
BlackSphere = 2
};
unsigned short horizontalDimensions;
unsigned short verticalDimensions;
public:
Tile(){}
~Tile(){}
void Update();
void Draw();
};
Tile.cpp file:
#include "stdafx.h"
#include "Tile.h"
void Tile::Update()
{
}
void Tile::Draw()
{
}
The attempt at filling the array in Grid.cpp is returning via the compiler the following error message: "Error 1 error C2061: syntax error : identifier '{ctor}'"
MSDN helped me giving me this:
"Compiler Error C2061. The compiler found an identifier where it wasn't expected. Make sure that identifier is declared before you use it."
I have failed at analysing it's meaning. What exactly have I done wrong here ? And what other problems are there to be found in my project? All help and comments will be much appreciated. Just assume I know 0% of C++
#user428435. Three things:
8x8 is 64, not 36
What kind of problems are you having? If a compilation error, what is the error? Often careful reading of the errors can help you solve your problems. If the code compiles and runs, what does it do that you don't expect it to do?
You probably meant
Tile* tileList_ptr[36];
If you want to allocate memory on the Heap, you have to use an allocation operator like "malloc" or "new"
Your example would, if written correctly only increase the Constructors stack size.
Correct Version of the Stack Memory:
Tile tileList_ptr[36];
Correct Version of the Heap Memory:
Tile* tileList_ptr = new Tile[36];
However, if you use "new" or "malloc" you have to remember to use "delete" or "free" when you don't need the allocated memory anymore...
typedef unsigned short Tile; // <= assuming typo
class Grid
{
...
public:
Grid()
{
}
...
private:
Tile tileList[64]; // <= 8x8=64
};
If the number of tiles is fixed at compile-time, why not store an array of tiles, instead of an array of pointers to tiles?
I am laughing. Your code, it's kind of full of fail :P
First tip: If you can avoid heap allocating, do. If your playfield is always 8x8, don't waste time with the heap (allocating the actual game class on the heap is another matter).
Second tip: Don't do that crappy typedef unsigned short USHORT thing. It's an unsigned short. Just use the type directly. USHORT is not going to change to not be an unsigned short. Plus, ALLCAPS names are reserved for macros. You probably picked this up from the Windows headers, they also use this. Really, it's a TERRIBLE idea.
Thirdly, 8x8 = 64, not 36, and you can just directly say 8x8.
What you want is something like this:
class Grid {
Tile grid[8][8];
public:
Grid() {
}
Tile* operator[](int index) {
return grid[index];
}
const Tile* operator[](int index) const {
return grid[index];
}
...
};
Possibly you mean this:
Tile tileList_ptr[36];
or this:
Tile* tileList_ptr[36];
Why does this code stop with segmentation fault :
class MapFile
{
public:
/* ... */
std::map <unsigned int, unsigned int> inToOut;
};
bool MapFile::LoadMapFile( const wxString& fileName )
{
/* ... */
inToOut.insert( std::make_pair(input,output) );
}
but when I put the "std::map inToOut;" just before "inToOut.insert" it works just fine :
class MapFile
{
public:
/* ... */
};
bool MapFile::LoadMapFile( const wxString& fileName )
{
/* ... */
std::map <unsigned int, unsigned int> inToOut;
inToOut.insert( std::make_pair(input,output) );
}
?
OK. Thanks guys, it seems that I have fixed this issue thanks to your help.
The problem was in the part of the code where I've been calling the LoadMapFile :
void WizardProductPage::OnTestButtonMapFile( wxCommandEvent& event )
{
wxString filename;
filename = locMapFile->GetValue();
MapFile::LoadMapFile( filename );
}
Should be :
void WizardProductPage::OnTestButtonMapFile( wxCommandEvent& event )
{
wxString filename;
filename = locMapFile->GetValue();
MapFile mapFile;
mapFile.LoadMapFile( filename );
}
I guess your problem is somewhere else. The following code works ok:
class MapFile
{
public:
std::map <unsigned int, unsigned int> inToOut;
void LoadMapFile();
};
void MapFile::LoadMapFile()
{
inToOut.insert( std::make_pair(1, 1) );
}
int main() {
MapFile a;
a.LoadMapFile();
return 0;
}
Try step-by-step debugging or post your whole code here, because this has no problems in it.
Also, yes. If you're trying to do that operation from different threads simultaneosly without locking, it could cause segfault.
Most likely you have a buffer overflow or a bad pointer that has caused you to trash the map when it's a member of your class. When you have the class an an auto variable, it is somewhere else in memory and your original bug is trashing some other piece of memory.
You should run your code under a memory debugger. If you are on Linux, I would recommend Valgrind
Maybe your application is multi-threaded and you are not locking insertion into map. Second variant doesn't share map with other threads.
It's possible that you called the member function on a object that has been deleted.
eg.
MapFile *p;
{
MapFile a;
p = &a;
}
p->LoadMapFile("test.map");
Would produce the error you described. The second case would not since you are not dereferencing the this pointer at any time.
edit: Maybe not, in the case that the input,output variables are member data then my answer would be incorrect.
Other reason for this kind of problem could be using a map with custom comparator and/or allocator and not initializing the map accordingly, which could generate segmentation faults at any random point, ie: the first insert could work perfectly, but on the second one, when the compare function is called, there could be a segmentation fault.