I'm writing a program for my friends during my summer time and I occurred really strange problem.
I'm assigning a QVector< T > to other QVector< T > with operator= in my homemade template class and then trying to check whethere this 2nd QVector< T > have any elements. First, I'm checking it's size and it's good, but when I use operator[] and function GetName() which is a member of class T.
Here's some code:
template <template T> class Turniej {
private:
QVector<T>* list_;
QVector<Stol<T> > stoly_;
int round_;
int max_rounds_;
Turniej() {round_=1;}
public:
static Turniej& GetTurniej() {
static Turniej turniej;
return turniej; }
void SetList(QVector<T> *list) {list_=list; }
QVector<T>& GetList() {return *list_;}
//Some other irrelevant methods
};
Then I invoke SetList() function with reference to QVector filled with 2 objects of Gracz class
Turniej<Gracz>::GetTurniej().SetList(&list)
And when I'm finally trying to get to the list_ object in Turniej class by code below, I get this error:
ASSERT failure in QVector::operator[]: "index out of range", file .../QtCore/qvector.h, line 356
qDebug()<<Turniej<Gracz>::GetTurniej().GetList()[0].GetName();
Where GetName() returns some QString and for certain that method exists in Gracz class.
I would really appreciate any help, because I'm stuck with it for 2 days and have completely no idea what's going on. What is strange, I was trying to google that error but I haven't found any topic with error in that particular line of qvector.h.
I'm using Qt 5.0.2 with Qt Creator
Thanks for any help!
when you call SetList, you are transferring the ownership of the list, are you shure you are not deleting it (or it is not getting deleted automatically) afterwards?
Change list_=list; to list_ = new QVector(list). Maybe your vector is modified somewhere outside of your class? You're just keeping reference to vector given to your method, it seems like copying is what you want.
updated
I see your class is a singleton. Always remember to think twice before making a class a singleton - it's not a thing you want to have in your code, and it should be avoided when possible.
Related
I use a SFML library for graphics and other stuff,such as vectors. In my Brain class I try to do something like:
class Brain{
Brain(int size){
Vector2f directions[size];
}
}
But it throws an error saying it must evaluate to a constant. I tried all sorts of things but I can't get it to compile properly. Anyone knows why this happens and how can I fix it?
As suggested in the comments in C++ the size of an array must be known at compile time... if you need dynamic containers you can use std::vector.
class Brain {
public:
Brain(int size) : _directions{size}
{
}
private:
vector<Vector2d> _directions;
};
Don't forget public and private access to your class... By default everything is private on a class so in your snippet the contructor of the class is private!
Here is my problem. I am supposed to make a python code able to fill a C++ vector of pointer on object of a class of the c++ code. I am using Boost::Python.
It's look as follow:
C++ code:
class A_Base {}
class A_derived_1 {}
...
class A_derived_N {}
class B {
...
setAderivediList(vector<A *> &_AderivedList){}
}
What I need to do in Python:
B.setAderivediList(_AderivedList)
I cannot modified the method in the C++ code, I can only add other objects in-between #ifdef python_interface in order not to impact other developpers work.
At first, I tried to write a converter from what I found on the Internet, but I failed to make it works for my code. Then I tried to add a _AderivedList in class B and a setter which fill the vector. Though it compile in C++, it dosen't work in Python.
New B class:
class B {
...
setAderivediList(vector<A *> &_AderivedList){}
#ifdef myPython_code
public:
vector<A *> * _AderivedListPy;
setAListPy(A * &my_Aderived){ //Actually, I tried without the reference as well
this->_AderivedListPy->push_back(my_Aderived);
};
#endif
}
In python it becomes:
myB = mydll.B()
Ai = mydll.A_derived_i()
myB.setAListPy(Ai) #stopping here
myB.setAderivediList(myB._AderivedListPy)
If I use the reference, it will throw a "python argument types did not match C++ signature" error message at myB.setAListPy(Ai), without the reference, it will stop at the same line without throwing any error message.
Any clue of how I could improve this or any other way to do it?
Thank you in advance.
Actually, I found a solution to my issue.
By filling the vector (including calling setAderivediList) directly in setAListPy.
I just pass an int my_A_derived to setAListPy (actually, along with other arg required by all A_derived class constructors) and use a if condition on my_A_derived.
I'm having some trouble with vector class. For some reason, yet to be found :P, I can't insert any objects to my vector. I've tried vector, map, deque, etc, but they all have the same weird result.
The object that I want stored is a class with 2 std::string in it. Here's some code to explain my point:
vector<DnsAddress> * dnss = new vector<DnsAddress>;
for(int i = 0; i < ns.size(); i++){
DnsAddress dn;
dn.SetRecord1(record1);
dn.SetRecord2(record2);
cout<<dn.GetRecord1()<<" : "<<dn.GetRecord2()<<endl; //this works, so it is inserting info to the object
dnss->push_back(dn);//this is where it begins to fail...
cout<<dnss->at(i).GetRecord1()<<" : "<<dnss->at(i).GetRecord2()<<endl;//doesn't work
DnsAddress a = dnss->at(0);//this way doesn't work either...
cout<<"dns: "<<a.GetRecord1()<<endl;
}
I'm sure there must be a rookie mistake.. I hate when those happen.. They consume me some time to find out.
Can someone give a hand with this?
I appreciate it :)
To claify:
There are no errors... It works without problem... but the info in the vector gets counted(.size() function tells me the number of inserted objects) but when you try to access it, nothing is shown... But no error is raised
This is class DnsAdress:
class DnsAddress {
public:
DnsAddress();
DnsAddress(const DnsAddress& orig);
virtual ~DnsAddress();
void SetRecord2(string record2);
string GetRecord2() const;
void SetRecord1(string record1);
string GetRecord1() const;
private:
string record1;
string record2;
};
This is just a guess since you didn't show your class DnsAddress or tell us what the error was.
My guess:
Your class doesn't have a copy constructor (compile time error) or
The copy constructor isn't making a correct copy (run time misbehavior).
I'll bet your DnsAddress class needs a copy constructor. This effectively gets invoked when you call push_back on a vector of non-pointer elements.
Edit: Looks like you do have a copy constructor. Actually if you just deleted the copy constructor, the default one would work fine. If you still want to implement it manually, you'll need to assign record1 and record2 to to orig.record1 and orig.record2 in your copy constructor implementation.
In my game I created a base class called Entity which I store in a set for processing. All my game objects derive from this class, and I have no problem adding the derived pointer types to the set in my initialization function.
The problem lies in adding new elements from within an Entity's Step() function. Now, before I get too far into it I'll show you some simplified code:
class GameState
{
public:
GameState();
~GameState();
...
set<Entity*> entities;
void Add(Entity* e);
void Remove(Entity* e);
protected:
set<Entity*> added, removed;
};
class Entity
{
public:
Entity();
Entity(GameState* parent);
virtual ~Entity();
virtual void Step(const sf::Input& input);
...
virtual void Destroy();
protected:
GameState* game;
};
The functions Add and Remove in GameState simply add the argument e to the added and removed sets respectively. In the main loop (elsewhere in GameState), I move the elements from added to entities before processing and after processing I remove elements from removed from entities. This ensures that entities is not modified during iteration.
The Add/Remove functions are very simple:
void GameState::Add(Entity* e)
{
added.insert(e);
}
void GameState::Remove(Entity* e)
{
removed.insert(e);
}
Every derived Entity is passed a pointer to GameState in it's constructor that it keeps as game. So theoretically from the Step function I should be able to Add and Remove entities with a simple call like game->Remove(this);, but instead I get a segfault. After a night of googling and coming up with nothing, I was able to work around (part of) the problem by implementing Entity::Destroy() like so:
void Entity::Destroy()
{
game->Remove(this);
}
So my first question is: Why does this work when I'm in the base class but not in the derived class?
Even more puzzling to me is Add(). Why does Add(new Explosion(16,16,this)) work in GameState but game->Add(new Explosion(16,16,game)) doesn't work inside my object?
I ran it through gdb and it tells me:
Program received signal SIGSEGV, Segmentation fault.
At c:/program files (x86)/codeblocks/mingw/bin/../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:482
The code that throws the error is:
_Link_type
_M_begin()
{ return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } //this line
So to sum it up I have no idea why my pointers break the STL... and I get that grave feeling that I'm missing something very basic and its causing all these headaches. Can anyone give me advice?
Why does Add(new Explosion(16,16,this)) work in GameState but
game->Add(new Explosion(16,16,game)) doesn't work inside my object?
If that is the case then the only possible explanation is that the Entity's game member doesn't actually point to the GameState. Check that it is being set properly on construction and verify before you use it.
This has nothing to do with std::set. The problem is that you are using an std::set that is part of a class that you are accessing via a corrupt pointer.
I don't have much experience with Qt but somehow I think this is acting strange.
Compiled with VS2005:
class Entry
{
public:
Entry(const QString& aName, bool checked) :
name(aName), isChecked(checked)
{
// empty
};
Entry(const Entry& entry) :
name(entry.name), isChecked(entry.isChecked)
{
// empty
};
Entry& operator=(const Entry& entry)
{
name = entry.name;
isChecked = entry.isChecked;
return *this;
}
QString name;
bool isChecked;
};
typedef QList<conduit::Entry> EntryVector;
When using EntryVector in the following lines, the entry in QList becomes a bad pointer:
void EntryWidget::setEntries(QStringList& names)
{
QStringList::iterator member;
EntryVector list;
for (member = names.begin(); member != names.end(); ++member)
{
Entry entry(*member, false);
list.append(entry);
}
m_model.setEntryData(list);
}
Somehow, entry.name in the list will become a bad pointer. My understanding is that QList should be able to support any data in its template, but for some reason that I yet do not understand this does not work. Everything works just fine if I use a STL Vector.
Any ideas? Thanks
I had this same problem, and came looking for anwsers.
I though my code was misbehaving, when it's not.
VS2005 debugger doesn't show you the things in QList correctly.
And as davmac suggested, when you print the stuff out, it works fine.
And davmac, please don't point out that he might have a memory corruption when the guy gives you a piece of code to try. If you can't try it with the same setup, that's another thing.
"entry.name" isn't a pointer - it's declared as a QString, here:
public: QString name;
So, what do you mean by "entry.name will become a bad pointer"?
Most likely, some other part of your program is causing a memory corruption.
I assume, that QStringList makes a depth-copy of the Strings in its copy-ctor.
And we know QList makes no depth-copy. see QList and implicit sharing
So, at the call of
void EntryWidget::setEntries(QStringList& names) {...}
Strings in names are copied.
But when you set the new Entry-List to the model,
m_model.setEntryData(list);
the list is not copied into mmodel.xy.
Now you can access mmodel.xy, but the strings you assign in setEntries(..) are already deleted.
They lost their scope, when you leave the setEntries(..) method.
Note:
QString is a reference pointer to a String. This is called "implicit sharing" .
And all containers in Qt have the concept of lazy-evaluation.
(Probably except the QStringList, which makes a depth-copy. This is perhaps a little bug in Qt. I can it only say 100% if I see the .cpp)
qt-project.org/doc/qt-5/qstringlist.html#QStringList-3