What could cause this?
Here's the stack trace:
#0 0x0645c0f5 in std::_Rb_tree_increment (__x=0x83ee5b0)
at ../../../../libstdc++-v3/src/tree.cc:69
#1 0x0805409a in std::_Rb_tree_iterator<std::pair<std::string const, Widget*> >::operator++ (
this=0xbffff144)
at /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_tree.h:192
#2 0x08053d32 in Generic::StartLayout (this=0x8287d68) at Generic.cpp:195
#3 0x0804f6e1 in LCDControl::ConfigSetup (this=0xbffff26c) at LCDControl.cpp:91
#4 0x0804ed7c in LCDControl::Start (this=0xbffff26c, argc=1, argv=0xbffff404) at LCDControl.cpp:21
#5 0x08050964 in main (argc=1, argv=0xbffff404) at Main.cpp:11
And here's the code:
for(std::map<std::string,Widget *>::iterator w = widgets_.begin();
w != widgets_.end(); w++){
if( w->second->GetType() & WIDGET_TYPE_BAR) {
w->second->SetupChars();
}
w->second->Start();
}
Edit: This next problem is related, so I won't open a whole new question. I'll leave the answer acceptance like it is. I just need to know something. I have two iterators, one main and one within that main after a function call. They both relate to the same map. Well, the one inside gets all corrupted, and the main one's loop stops iterating.
Here's the code.
Here's StartLayout:
void Generic::StartLayout() {
Error("StartLayout: %s", key.c_str());
for(std::map<std::string,Widget *>::iterator w = widgets_.begin();
w != widgets_.end(); w++){
Error("Starting widget %s", w->first.c_str());
if( w->second->GetType() & WIDGET_TYPE_SPECIAL) {
w->second->SetupChars();
}
w->second->Start();
}
}
And here's SetupChars():
void WidgetGif::SetupChars() {
Error("SetupChars <%s> <%s>", name_.c_str(), widget_base_.c_str());
Error("Size of widgets: %d", visitor_->Widgets().size());
std::map<std::string, Widget *> widgets = visitor_->Widgets();
for(std::map<std::string, Widget *>::iterator ii=visitor_->Widgets().begin();
ii != visitor_->Widgets().end(); ii++) {
Error("<%s> Widget base %s == %s", ii->first.c_str(), ii->second->GetWidgetBase().c_str(), widget_base_.c_str());
if(ii->second->GetWidgetBase() == widget_base_ &&
((WidgetGif *)ii->second)->HasChars()) {
Error("Using chars from %s", ii->first.c_str());
for(unsigned int i = 0; i < rows_ * cols_; i++ ) {
if(i >= visitor_->GetLCDText()->CHARS) {
Error("1) GIF too large: %s, %d", name_.c_str(), visitor_->GetLCDText()->CHARS);
if(update_) delete update_;
update_ = new Property(visitor_, section_, "", new Json::Value("-1"));
return;
}
ch_[i] = ((WidgetGif *)widgets[ii->first])->GetChars()[i];
}
hasChars_ = true;
return;
}
}
// It goes on, but I snipped it here.
}
And this is what happens:
StartLayout: display_qt
Starting widget widget_gif_american_flag:layout_american_flag:0
SetupChars <widget_gif_american_flag:layout_american_flag:0> <layout_american_flag>
Size of widgets: 5
<widget_gif_american_flag:layout_american_flag:1> Widget base layout_american_flag == layout_american_flag
<widget_gif_american_flag:layout_american_flag:4> Widget base layout_american_flag == layout_american_flag
<(n
(n
��S> Widget base ГS == layout_american_flag
^C
Last edit: I figured it out. I just needed a copy of the original map for the new iterator.
There could be quite a few reasons for that. For one, it may be that GetType or SetupChars or Start do something that causes your map to change - which would invalidate the current iterator (note that using operator[] on the map, even just to read the value, is technically a mutating operation, and can cause a crash with iterator debugging enabled!). Alternatively, your map could be corrupted in memory by some code that executed before, e.g. because of a buffer overrun overwriting part of the map's tree.
You must not modify widgets_ in any of your methods GetType, SetupChars, or Start. This is most likely your problem.
If you must modify widgets_, then you will need to restart the iterator whenever such a change is made. To avoid duplicating your changes, you can use a simple marker dictionary outside the loop, or a marker member of the Widget class.
Related
EDIT: thanks to Scheff and everyone else who commented
I am currently attempting to communicate with a serial device and have to change a foreach loop into a range based for loop. In order to do this I have written the following code:
std::vector<QSerialPortInfo> serialList;
for (QSerialPortInfo const &serialPortInfo : serialList)
{
qDebug() << "check/n";
if (serialPortInfo.hasVendorIdentifier () && serialPortInfo.hasProductIdentifier ())
{
if (serialPortInfo.vendorIdentifier () == trackerVendorID &&
serialPortInfo.productIdentifier () == trackerProductID)
{
trackerPortName = serialPortInfo.portName ();
trackerIsAvailable = true;
}
}
}
The problem is that this just generates an empty vector so the for loop is never used and the qDebug "check" is never called. I know I need to put something in with QSerialPortInfo::availablePorts() but I can't for the life of me work out how.
You write:
std::vector<QSerialPortInfo> serialList;
But QSerialPortInfo::availablePorts() does not return a std::vector, it returns a QList<QSerialPortInfo>, which you can use as is in the for loop:
QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo& serialPortInfo : serialList)
{
...
I asked this question about a half hour ago, but the code had typos and I wasn't being very clear, so I've deleted and I'm trying again with a better format.
I'm getting a Segmentation Fault in my code, the problem seems to be at the function call if( (*trans).test((*this), *(*itr)) ) inside World::update():
void World::update(sf::Time dt)
{
mPlayer->setVelocity(0.f, 0.f);
while (!mCommandQueue.isEmpty()){
Command cmd = mCommandQueue.pop();
cmd.action(cmd.node, dt);
}
mSceneGraph.update(dt);
adaptPlayerPosition();
//Enemy Spawn engine
if (mSpawnTimer.getElapsedTime().asSeconds() >= SPAWN_INTERVAL && mEnemies.size() < MAX_NUM_ENEMIES){
float winX = mWindow.getDefaultView().getSize().x;
float winY = mWindow.getDefaultView().getSize().y;
float x = rand() % (int)winX;
float y = rand() % (int)winY;
spawnEnemy(x, y, EnemyType::Loner, IState::ILWander);
mSpawnTimer.restart();
}
// FSM update
IState::ID curEnemyStateID;
FState curEnemyState;
bool trigger = false;
ICondition triggeredtrans;
FState triggeredState;
for(auto itr = mEnemies.begin(); itr != mEnemies.end(); ++itr){
curEnemyStateID = (*itr)->getState();
// set curState to whatever the enemy's curState is
switch(curEnemyStateID){
case 0:
curEnemyState = LWander;
break;
default:
break;
}
auto tState = curEnemyState.getTransitionStates().begin();
for(auto trans = curEnemyState.getConditions().begin(); trans != curEnemyState.getConditions().end(); ++trans){
if( (*trans).test((*this), *(*itr)) ){
trigger = true;
triggeredState = (*tState);
break;
}
++tState;
}
if(trigger){
(*itr)->setState(IState::ILRushPlayer);
curEnemyState = LRushPlayer;
}
curEnemyState.getAction()->doAction((*this), *(*itr));
}
}
Context:
trans is an iterator for a std::vector<ICondition> conditions where each ICondition has a test(World& world, Enemy& enemy). itr is an iterator through a std::vector<Enemy*> that is held by World.
The conditions vector is filled in this function:
void World::initializeStates()
{
Wander LWanderAction;
LWander.setAction(LWanderAction);
DistFromPlayer LWanderCond1(30);
LWander.pushCondition(LWanderCond1);
LWander.pushTransitionState(LRushPlayer);
}
LWander is a state (FState) in my Finite State Machine. Wander is a class that inherits IAction, and setAction accepts an IAction parameter: FState::setAction(IAction iact)
DistFromPlayer is a class that inherits ICondition.
FState::pushCondition(ICondition icond) and FState::pushTransitionState(Fstate state) should take their arguments and push them to Fstate's conditions and states vectors. (A transition's condition and matching target state should be at the same indices in both)
LWander and LRushPlayer are both members of World.
And that should cover everything. I don't know why I'm getting a SegFault, but I'm assuming that the problem is with how things are pushed into LWander in World::initializeStates(). I should also note that the SegFault occurs right after the first enemy is spawned in my game, which is also the same update frame that runs (*trans).test(*this, **itr) for the first time. All Enemys start in the LWander state.
ICondition's virtual bool test(World& world, Enemy& enemy); is defined as:
bool ICondition::test(World& world, Enemy& enemy){
return false;
//returns false by default, overwritten later
}
and DistFromPlayer's bool test(World& world, Enemy& enemy); is defined as:
bool DistFromPlayer::test(World& world, Enemy& enemy)
{
std::cout << "DistFromPlayer (LWander's Transition) was reached\n";
return false;
}
and only contains a print statement for debugging purposes.
GDB's backtrace
#0 World::update (this=0x6464408, dt=...) at C:\...\World.cpp:97
#1 0x0040416b in GameState::update (this=0x64643f0, dt=...) at C:\...\GameState.cpp:22
#2 0x00402435 in StateStack::update (this=0x28fde0, dt=...) at C:\...\StateStack.cpp:19
#3 0x00403782 in Game::update (this=0x28fbc0, elapsedTime=...) at C:\...\Game.cpp:58
#4 0x004036a2 in Game::run (this=0x28fbc0) at C:\...\Game.cpp:48
#5 0x0040888b in main () at C:\...\main.cpp:7
I am suspecting tState iterator. You only initialize it with begin() and increment it. I can't find any test against end() of the appropriate container. Or is it safe because of some relation between curEnemyState.getTransitionStates() and curEnemyState.getConditions() which I don't realize?
I have a QVector in which I'm constantly appending data so I can plot on a QwtPlot. But with a high frequency I guess the vector becames too large and the program crashes.
My question is, how can I create a QwtCurve which is only beggining in some point of time, bacause the time that has already passed is not necessary in the vector as it was already plotted.
here's my code:
QVector<double> xv;
QVector<double> cv1;
QVector<double> cv2;
as global variables,
void gui::process_new_info(QByteArray array)
{
int v = 0;
double f = ui->frequency->value();
xv.append(sizeof_array/f);
char *buf = array.data();
if (ui->ecgPlux->isChecked() == true || ui->channel_1->currentIndex() != 0)
{
cv1.append(buf[1]);
QwtPlotCurve *curve1 = new QwtPlotCurve;
curve1->attach(plot_all[0]);
curve1->setData(xv,cv1);
curve1->setPen(QPen(Qt::blue,1));
plot_all[0]->replot();
QwtPlotCurve *curve2 = new QwtPlotCurve;
curve2->attach(plot[0]);
curve2->setData(xv,cv1);
curve2->setPen(QPen(Qt::blue,1));
plot[0]->replot();
}
if (ui->xyzPlux->isChecked() == true || ui->channel_2->currentIndex() != 0)
{
cv2.append(buf[2]);
QwtPlotCurve *curve3 = new QwtPlotCurve;
curve3->attach(plot_all[1]);
curve3->setData(xv,cv2);
curve3->setPen(QPen(Qt::blue,1));
plot_all[0]->replot();
QwtPlotCurve *curve4 = new QwtPlotCurve;
curve4->attach(plot[1]);
curve4->setData(xv,cv1);
curve4->setPen(QPen(Qt::blue,1));
plot[1]->replot();
}
//printf ("%d ->", buf[0]);
fprintf (data, "%d,", buf[0]);
for (int i = 1; i < 9; i++)
{
v = buf[i];
//printf ("%d,", v);
fprintf (data, "%d,", v);
}
//printf ("\n");
fprintf (data, "\n");
sizeof_array++;
}
QwtPlotCurve
http://qwt.sourceforge.net/class_qwt_plot_curve.html
inherits from QwtPlotSeriesItem
http://qwt.sourceforge.net/class_qwt_plot_series_item.html
There is a warning in setData
The item takes ownership of the data object, deleting it when its not used anymore.
It probably isn't the fact that you are growing too big... it may be that you are accessing something that Qwt deleted.
Run it in a debugger, and look at the stack trace for where it died, or put in a bunch of qDebug() lines to see where it is dying.
If it is something with the data being too large, you could pop off items off of the head of your vector, before setting the vector.
Hope that helps.
I have a sfml window container, and it appears to be working, however the glViewPorts are the wrong size, which I assume is because the wrong sf::Window is being passed.
Here is a function which adds to the window: It takes some information about the sfml window.
int WindowContainer::PushBack(WindowData& data)
{
if(data.WindowSettingsOK() && data.VideoModeOK()){
mWindowVector.resize(mWindowVector.size() + 1);
mDisplayFuncVector.resize(mWindowVector.size());
mInputFuncVector.resize(mWindowVector.size());
mWindowVector.at(mWindowVector.size() - 1) = new sf::Window();
mWindowVector.at(mWindowVector.size() - 1)->Create(data.VideoMode(), data.Title(), data.Style(), data.Settings());
mWindowVector.at(mWindowVector.size() - 1)->SetPosition(data.PositionX(), data.PositionY());
mDisplayFuncVector.at(mWindowVector.size() - 1) = nullptr;
mInputFuncVector.at(mWindowVector.size() - 1) = nullptr;
return 0;
}
else{
PrintError(ErrorMessageType::BadSettings);
return 1;
}
}
Alternatively, this function may be called to setup the display and input function callbacks:
int WindowContainer::PushBack(WindowData& data, function_p displayFunc, function_p inputFunc)
{
int return_val = PushBack(data);
mDisplayFuncVector.at(mWindowVector.size() - 1) = displayFunc;
mInputFuncVector.at(mWindowVector.size() - 1) = inputFunc;
return return_val;
}
Then, when the window needs .Display()'ing, this function is called:
void WindowContainer::ProcessDisplay()
{
for(unsigned int i = 0; i < mWindowVector.size(); i ++){
if(mDisplayFuncVector.at(i) != nullptr){
mDisplayFuncVector.at(i)(*mWindowVector.at(i), mClock, (const void*&)mExternalDrawingDataPointer);
}
mWindowVector.at(i)->Display();
}
}
... This is all good, until the result on the screen is that resizing one window affects the viewport of both windows. This suggests that calling the callback function: mDisplayFuncVector.at(i)(*mWindowVector.at(i), mClock, (const void*&)mExternalDrawingDataPointer); gives the argument of *mWindowVector.at(0) each time, instead of each window individually. (As in *mWindowVector.at(i))
Can anyone help with this problem?
The main loop contains this code:
while(container.Access(0)->IsOpened()){
container.ProcessInput();
container.ProcessDisplay();
}
Container.Access(int) is this function:
const sf::Window*& WindowContainer::Access(unsigned int index)
{
if(index > mWindowVector.size()){
PrintError(ErrorMessageType::IndexOutOfRange);
}
else{
return (const sf::Window*&)mWindowVector.at(index);
}
return (const sf::Window*&)mWindowVector.at(0);
}
Thanks again, I'm sure I have made a mistake somewhere but cannot spot it.
I have been thinking about this question and suspect openGL becomes confused with which window is it drawing to if more than one object is pushed back without a call to Display() to sync everything.
I am yet to test this and confirm.
EDIT The window container now works. It has nothing to do with the callback functions argument.
For some odd reason, my application likes to break on me when I switch to release and run it outside of my debugger. Here's what works for me, and here's what doesn't
(Qt Creator is the IDE)
Debugging with debug configuration - ok
Running with debug configuration - ok
Debugging with release configuration - ok
Running with release configuration - application crash
My UI is one project, and the core for some stuff as a separate dependency. On Windows (compiling with MSVCC), I hit a menu button, which eventually calls down to a function. In that function, the app breaks on adding a new element to a vector. e.g:
str *x = new str();
str *y = new str();
/* ...set some of x & y's members... */
vector.push_back(x); // works fine
vector.push_back(y); // causes crash
If I comment out the line vector.push_back(y);, the app continues no problem until the app leaves the event scope (i.e. the end of OnMenuButtonClick). On OS X, it's similar to the issue of adding an element to a vector, except I have:
std::vector<foo *> SomeFunction()
{
std::vector<foo *> returningVector;
/* do stuff */
std::vector<foo *> goo = GetFooObjects();
for (int i = 0; i < goo.size(); i++)
{
returningVector.push_back(goo[i]); // breaks here
}
}
So what are some causes of this strange behavior without a debugger attached and not under debug configuration? I've checked to make sure all of my variables are initialized, so I'm stumped. If you want to view the code above, the first part can be located here, and the second part here. Please forgive anything you see as "bad", and if you have suggestions that you just can't contain, then please do message me on GitHub.
Edit:
I looked more into it, and found out exactly what's causing the problem, but don't know how to fix it. This is the function where my app crashes (on OS X):
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
vector<Drive *> Return;
if (HardDisks)
{
vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();
for (int i = 0; i < (int)Disks.size(); i++)
{
DISK_DRIVE_INFORMATION ddi = Disks.at(i);
// First, try reading the disk way
Streams::xDeviceStream* DS = NULL;
try
{
char path[0x200] = {0};
wcstombs(path, ddi.Path, wcslen(ddi.Path));
DS = new Streams::xDeviceStream(ddi.Path);
}
catch (xException& e)
{
continue;
}
if (DS == NULL || DS->Length() == 0 || DS->Length() < HddOffsets::Data)
{
// Disk is not of valid length
continue;
}
DS->SetPosition(HddOffsets::Data);
// Read the FATX partition magic
int Magic = DS->ReadInt32();
// Close the stream
DS->Close();
// Compare the magic we read to the *actual* FATX magic
if (Magic == FatxMagic)
{
Drive *d = new Drive(Disks.at(i).Path, Disks.at(i).FriendlyName, false);
Return.push_back(d);
}
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < (int)LogicalDisks.size(); i++)
{
Return.push_back(LogicalDisks.at(i));
}
return Return;
}
If I change if (HardDisks) to if (HardDisks = false), the app works just fine. So, I looked into that scope and discovered that after vector<DISK_DRIVE_INFORMATION> Disks = GetPhysicalDisks();, the heap gets corrupt or something like that. I noticed this because in the debugger, after that function is called, my HardDisks bool changes to "false", which wasn't what it was before.
Here is GetPhysicalDisks:
vector<Drive::DISK_DRIVE_INFORMATION> Drive::GetPhysicalDisks( void )
{
// RIGHT AFTER this vector is initialized, everything goes to hell
vector<Drive::DISK_DRIVE_INFORMATION> ReturnVector;
DIR *dir;
dirent *ent;
dir = opendir("/dev/");
if (dir != NULL)
{
// Read the shit
while ((ent = readdir(dir)) != NULL)
{
// Check the directory name, and if it starts with "disk" then keep it!
QRegExp exp("disk*");
exp.setPatternSyntax(QRegExp::Wildcard);
exp.setCaseSensitivity(Qt::CaseInsensitive);
if (exp.exactMatch(ent->d_name))
{
DISK_DRIVE_INFORMATION curdir;
memset(curdir.FriendlyName, 0, sizeof(curdir.FriendlyName));
memset(curdir.Path, 0, sizeof(curdir.Path));
char diskPath[0x50] = {0};
sprintf(diskPath, "/dev/r%s", ent->d_name);
mbstowcs(curdir.Path, diskPath, strlen(diskPath));
int device;
if ((device = open(diskPath, O_RDONLY)) > 0)
{
#ifdef __linux
hd_driveid hd;
if (!ioctl(device, HDIO_GET_IDENTITY, &hd))
{
swprintf(curdir.FriendlyName, strlen(hd) * 2, L"%hs", hd.model);
}
#elif defined __APPLE__
mbstowcs(curdir.FriendlyName, ent->d_name, strlen(ent->d_name));
#endif
ReturnVector.push_back(curdir);
}
}
}
}
return ReturnVector;
}
While this isn't a real answer as to what happened, I did find a way to fix the problem. Looking at my edit above, I edited my Drive::GetFATXDrives function like so:
vector<Drive *> Drive::GetFATXDrives( bool HardDisks )
{
// Initialize Disks vector up here
vector<DISK_DRIVE_INFORMATION> Disks;
// Call the function to get the hard disks
if (HardDisks)
Drive::GetPhysicalDisks(Disks);
vector<Drive *> ReturnVector;
if (HardDisks)
{
Streams::xDeviceStream* DS = NULL;
for (int i = 0; i < (int)Disks.size(); i++)
{
/* ... */
}
if (DS)
{
DS->Close();
delete DS;
}
}
vector<Drive *> LogicalDisks = GetLogicalPartitions();
for (int i = 0; i < LogicalDisks.size(); i++)
{
ReturnVector.push_back(LogicalDisks[i]);
}
return ReturnVector;
}
And my Drive::GetPhysicalDisks function now takes a vector<DISK_DRIVE_INFORMATION> reference instead of returning one. Seemed to make my program work just fine after that.