I'm writing a QT app and I'm very rusty with C++, so I'm guessing that's the problem. I've got a crash with an exc_bad_access signal on my Mac, which means I'm doing something wrong with memory. Here's my code:
void MainWindowController::showMainWindow() {
MainWindow *w = mainWindow();
w ->show();
}
MainWindow *MainWindowController::mainWindow() {
if (NULL != _mainWindow)
return _mainWindow;
// otherwise, we need to load it and return it
_mainWindow = new MainWindow(0);
return _mainWindow;
}
_mainWindow is an instance variable, a pointer (as you might have guessed from the function signature). It's a simple lazy-loading. I think I'm doing memory management OK, as this class owns the object (which is later deleted in the destructor).
The crash occurs on the w -> show(); line, QT complains its somewhere inside the QWidget show() function, which doesn't really make sense to me.
Can somebody help me out? Thanks!
Turns out it was something even simpler. I'm used to Objective-C, where ivars are automatically initialized to 0. C++ doesn't do this. So, I had to make sure _mainWindow was initialized to NULL in the constructor. Problem solved.
Related
I recently joined a new project, which is full with idiom like: ,
void foo()
{
Widget* temp = new Widget;
connect(temp, &Widget::signalTriggerred,[this, temp ]()
{
do cool staff...
}
}
As you can see no delete nothing, I am afraid even user class "Widget" is inherited QObject, this is still a leak. Does QT do something fancy to prevent leek in case above?
What I am planning to do:
void foo
{
std::shared_ptr<Widget > temp( new Widget () );
connect(temp.get(), &Widget::signalTriggerred,[this, temp] ()
{
do even cooler things...
}
}
Is there a problem with my apporach? (For example I didn't want to use .get() but compiler errors forced me to use it).
Edit : Since there is no parent in my case it is different. Duplicated question seek answer for parent-child cases. I am already aware in that case there will be no leek. In my question I am asking about creating a local QObject based object. And connecting it.
Not quite sure what you're wanting from the question, but if you need to delete the widget and it is derived from QObject, you can delete it in the lambda expression, assuming it's not going to be used after this scope:
void foo()
{
Widget* temp = new Widget;
connect(temp, &Widget::signalTriggerred,[this, temp ]()
{
temp->deleteLater();
}
}
This very much depends on the context.
If the temp widget is actually a visible top-level widget (no parent QWidget), then the widget needs to be kept alive until the user closes it. You can achieve it getting deleted automatically when being closed using:
widget->setAttribute(Qt::WA_DeleteOnClose);
If the temp widget however is inserted into the layout of some parent widget, Qt will automatically insert it into the QObject ownership tree and temp will have the same lifetime as its parent, see QObject::setParent().
The shared_ptr by itself saves nothing because it does not answer the question of intended lifetime of widget.
I've been running into problems with a C++ program that I've been working on recently. Specifically, I've been working on a program that uses Qt's GUI framework and I've been running into errors that seem to be related to double-deletion of pointers and exception handling. The issue is that I feel like the API that I'm using works in a way that isn't exactly predictable and because of that, I'm running into a lot of errors that seem counter-intuitive. I'm not the most experienced C++ programmer in the world, so maybe there is some overall strategy for working with new APIs that I'm missing..
Here's an example: I typically always try to delete objects that I dynamically allocate with inside the same class. In other words, if I populate a pointer using the new keyword within a class' constructor or init function, then I usually make sure to delete the contents of that pointer in the class' destructor.
Here's an simplified example of the class definition for the class that was giving me problems [MyProject.h]:
#ifndef MYPROJECT_H
#define MYPROJECT_H
#include "QObject.h"
class QGuiApplication;
class QQmlApplicationEngine;
#define MYPROJECT MyProject::getInstance()
class MyProject : public QObject
{
Q_OBJECT
private:
explicit MyProject(QObject *parent = 0); //singleton..
MyProject(MyProject const&); //uncopyable..
void operator=(MyProject const&); //unassignable..
QGuiApplication * QtGUI;
QQmlApplicationEngine * QmlAppEngine;
public:
~MyProject(void);
/* Globally available function to get MyProject's singleton instance.
* You can use the "MYPROJECT" preprocessor macro for shorthand. */
static MyProject & getInstance(void)
{
static MyProject instance;
return instance;
}
int init(int argc, char * argv[]);
int exec(void);
signals:
public slots:
};
#endif
This is what my simplified main.cpp looks like:
#include "MyProject.h"
int main(int argc, char * argv[])
{
MYPROJECT.init(argc, argv);
return MYPROJECT.exec();
}
Here's the ctor and init() that I initially had for that class [MyProject.cpp]:
MyProject::MyProject(QObject *parent) :
QObject(parent) ,
QtGUI(NULL) ,
QmlAppEngine(NULL)
{
}
MyProject::~MyProject(void)
{
//segfault: debug points to both of these..
if (QtGUI) delete QtGUI;
if (QmlAppEngine) delete QmlAppEngine;
}
int MyProject::init(int argc, char * argv[])
{
QtGUI = new QGuiApplication(argc, argv);
QmlAppEngine = new QQmlApplicationEngine();
if(QtGUI && QmlAppEngine)
{
//segfault: debug points to this..
QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyProject.qml") ));
}
else return 1;
}
int MyProject::exec(void)
{
return QtGUI->exec();
}
So, my plan was: ctor initializes pointers to NULL, init() populates those pointers with new objects, and if those pointers are not null the dtor cleans them up with delete. But this code crashes with 2 segfaults, but even though I think I've narrowed it down, I'm not sure I understand why they're both happening.
(1) Segfault #1 is a crash on startup that points to the "QmlAppEngine->load()" call inside the init(). I was able to prevent the crash from occurring by wrapping that function call in exception handling code like this:
int MyProject::init(int argc, char * argv[])
{
QtGUI = new QGuiApplication(argc, argv);
QmlAppEngine = new QQmlApplicationEngine();
if(QtGUI && QmlAppEngine)
{
//exception handling prevents crash..
try
{
QmlAppEngine->load(QUrl( QStringLiteral("qrc:///MyProject.qml") ));
}
catch(int e)
{
std::cout << "Exception: " << e << std::endl;
return 1;
}
return 0;
}
else return 1;
}
I'm not very familiar with exception handling, as most of the code I've written so far has used int return-code style error handling. I'm guessing that the load function can throw an exception in certain situations, and not handling them can cause a crash. The program stopped crashing on start-up once I made this change, but strangely, it didn't seem to actually throw an exception as my 'cout' never output anything.. Something else that I don't understand is that this code is called without any exception handling code in the default setup for brand new Qt Projects that Qt Creator makes - for example, this is what you see when you start a new QtQuick2 project in QtCreator IDE:
#include "QGuiApplication"
#include "QQmlApplicationEngine"
int main(int argc, char * argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine();
//default Qt file calls this without issue though..
engine.load(QUrl( QStringLiteral("qrc:///MyQml.qml") );
return app.exec();
}
The only major different that I can see here is that the default code uses objects instead of pointers to objects. But, in this case, load runs fine without exception handling code and there is no segfault..
(2) The next issue is caused when my dtor calls the delete keyword on those two pointers. If I comment out those two lines, the program runs fine and closes without crashes or issues. This leads me to believe that the API has made these objects delete themselves later, which is causing a segfault due to double-deletion when I also explicitly call delete. But, in general, how can one know if the API that they're using is taking care of object deletion internally? And, if I can't tell whether or not an API specified object is being deleted automatically, should I take any extra measures (i.e.: use some kind of smart pointer, etc.)? Typically I make the assumption that I should delete any dynamically allocated objects in the destructor of the same class, but clearly that can backfire in situations like this.
So what steps can I take to work with the APIs that I use in a way that (a) prevents bugs and (b) allows me to make sure that resources are being freed correctly and exceptions are being handled?
It's hard to find the exact location of error by seeing the sample code you provided, your application must have large code base and does many things with memory. Qt is a well designed and fully documented framework (though some documentation are misleading or outdated), I suggest you to read properly the documentation about a specific item if you have confusion. Here are some general issues I guess you should know/consider when using Qt:
When creating an object on the heap of class that inherits QObject, if you pass a parent ( another QObject) in the constructor, then the child object is owned by parent and memory will be freed automatically by the parent object.
QObject is NO_COPYABLE, so if you inherit from it, you don't need to make copy ctor/assignment operator private. The compiler generated versions of these methods calls parent version (here QObject), hence your class is automatically un-copyable/assignable.
new by default throws bad_alloc exception if it fails instead of returning NULL. So either you use try-catch or change default behavior by using no_throw version of new (new(std::nothrow)), it will return nullptr on failure.
deleteing a NULL pointer will not cause any problem. However, if the pointer points to arbitrary location / contain garbage value, deleteing it will result in segfault.
By default engine.load is not used with exception handler, so there is a high chance it does not raise exception. Look closely in other areas of your code.
I think I must be "doing something wrong" here. I have a program using gtkmm. The main window for the program is a subclass of Gtk::Window and I have the bare bones of the application drawn out in Glade.
Here's an edited version of the main window's constructor:
template<class T>
static T*
get_widget (Glib::RefPtr<Gtk::Builder> builder, const Glib::ustring& name)
{
T* widget;
builder->get_widget (name, widget);
if (! widget) no_such_widget (name);
return widget;
}
app_window::app_window ()
{
Glib::RefPtr<Gtk::Builder> builder;
try {
builder = Gtk::Builder::create_from_file (installed_ui_name);
}
catch (const Glib::FileError& err) {
g_error ("Couldn't open UI definition file at %s",
installed_ui_name);
throw;
}
// main_box is a std::unique_ptr<Gtk::Widget>, a field of app_window.
//
// This works fine: the Gtk::Box gets added as the main child of this
// app_window and survives until the app_window is destroyed.
main_box.reset (get_widget <Gtk::Box> (builder, "main-box"));
add (* main_box);
auto accel_group = get_accel_group ();
// This doesn't work so well
//
// menu_quit is a Gtk::MenuItem*. The object seems to be actually
// constructed for the call to builder->get_widget, because its existence
// stops the menu item from being finalized at the end of the application.
auto menu_quit (get_widget<Gtk::MenuItem> (builder, "menu-quit"));
menu_quit->add_accelerator ("activate", accel_group,
GDK_KEY_q, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
using std::bind;
menu_quit->signal_activate ().connect (bind (& app_window::on_close, this));
show ();
}
When setting up the window, I want to register various signal handlers for menu items etc. (the menu_quit widget in the example is just one of them). To do so, I think I need to use builder->get_widget() to get hold of an object to talk about.
The problem is that I've now got an instance of (a subclass of) Gtk::Widget and I don't know what to do with it. If I call delete on the pointer, the widget doesn't appear in the application, but no other problems happen. That's a bit confusing: I would expect either no effect or a segmentation fault (depending on whether something else thought it owned the object or not).
If, on the other hand, I leak the pointer, assuming that object will be owned by the container into which main_box has been added, I get a memory leak. In particular, menu_quit's underlying gtk_image_menu_item doesn't get finalised because the reference count is one too high. (I can check easily enough that with GDB)
A "solution" is to store a pointer to each object that I get with builder->get_widget as a field in the app_window and then delete it in the destructor (automated with std::auto_ptr or std::unique_ptr). But that's really horrible: I don't want to have to write out a field for every single menu item! Avoiding that sort of nonsense was the whole point of using GtkBuilder in the first place!
Assuming that this isn't a bug (gtkmm 3.12.0, if that's relevant), I assume I'm just doing it wrong. How is an application supposed to do this?
I have built myself a little entity based game framework that does no rendering or window management by itself but provides structure. An equivalent to an MVC framework really.
I am now trying to put it into practice by rendering a simple window with SFML 2. I have done it in the past in this environment (my Ubuntu 12.04 box) with more stringy code, so I know my SFML 2 libraries are working correctly.
I am however getting a segmentation fault when trying to access my sf::RenderWindow instance. I have run it through GDB and everything is there, but when trying to execute a method (which GDB can see), it dies.
This only happens though if I try to access my window like this.
class BasicGame : public arc::Game
{
public:
sf::RenderWindow window;
};
class BasicGameSystem : public arc::System
{
protected:
BasicGame* game;
};
class RenderSystem : public BasicGameSystem
{
public:
void start()
{
game->window.create(sf::VideoMode(640, 480), "Basic arc example");
game->window.setFramerateLimit(60);
}
};
The pointer, game, is not null. I can dereference it in GDB and it will return an instance of BasicGame. game->window also exists, and GDB can see game->window.create, it will even moan at me for not supplying any arguments if I try to execute it.
If I try to execute setFramerateLimit manually with GDB using a breakpoint it will also segfault.
If I change my start method to this though...
void start()
{
sf::RenderWindow window;
window.create(sf::VideoMode(640, 480), "Basic arc example");
window.setFramerateLimit(60);
}
It works absolutely fine. Well, the window closes instantly, but no segfault.
Does sf::RenderWindow need to be in the same scope? Does it's default constructor break it?
I am still pretty new to C++, so I may be doing something utterly stupid, but any help on this would be much appreciated. I have been searching and tinkering for hours but I just can't work it out. Hopefully this is enough information too.
Thanks.
Edit:
Just for a little more information. I am compiling with clang++ although I have tried g++ too with the same result. And here is the backtrace from GDB.
#0 0xb7cd0981 in sf::Window::close() () from /usr/local/lib/libsfml-window.so.2
#1 0xb7cd131e in sf::Window::create(sf::VideoMode, std::string const&, unsigned int, sf::ContextSettings const&) ()
from /usr/local/lib/libsfml-window.so.2
#2 0x080496a3 in RenderSystem::start (this=0xbffff0f0) at examples/basic.cpp:26
#3 0x0804b60e in arc::SystemList::add (this=0xbffff128, system=0xbffff0f0) at src/SystemList.cpp:17
#4 0x08049f79 in arc::Game::addSystem (this=0xbffff128, system=0xbffff0f0) at src/Game.cpp:11
#5 0x08048cfc in main () at examples/basic.cpp:73
I have no idea why close is being run... I have one occurrence in my codebase which is listening for the window close event. Taking it out makes no difference. Just thought I would make sure.
The pointer, game, is not null. I can dereference it in GDB and it will return an instance of BasicGame.
The key point is to have a valid instance of BasicGame. From the code snippet you gave, it looks like you didn't use new so your pointer is pointing to a non-allocated memory region.
Consider the following code :
int* x = new int;
*x = 58;
delete x;
std::cout << x << " points to the value " << *x << std::endl; // unpredictable behaviour!
After deleting x you still can print its old address but if you try to access its content you might (but not necessarily) crash your program.
To prevent such mistake your should always add x = 0; (or x = nullptr; in C++11) and initialise your attributs :
BasicGameSystem() : game(0) { }
This way, you will know when you access invalid memory region because your program will crash.
My program keeps crashing when I close the frame. I've narrowed the cause down to two lines of problematic code, but I'm not sure why they're crashing. Here's some of my code:
TetrisFrame.cpp
TetrisFrame::TetrisFrame()
: wxFrame(0, wxID_ANY, "Tetris")
{
statusController_ = new StatusController;
statusController_->setModel(new Statuses);
statusController_->addView(this);
tetrisController_ = new TetrisController;
tetrisController_->setStatusController(statusController_.get()); // Problem one
tetrisController_->setModel(new TetrisModel);
tetrisController_->addView(new Board(this)); // Problem two
}
TetrisFrame class private member variables:
wxSharedPtr<StatusController> statusController_;
wxSharedPtr<TetrisController> tetrisController_;
StatusController class private section:
typedef wxSharedPtr<TetrisFrame> ViewPtr;
wxSharedPtr<Statuses> model_;
std::vector<ViewPtr> views_;
Board class private member variables:
wxSharedPtr<TetrisController> controller_;
relevant TetrisController functions:
void TetrisController::setStatusController(
StatusController* statusControllerPtr)
{
statusController_ = statusControllerPtr;
}
void TetrisController::addView(Board* viewPtr)
{
views_.push_back(ViewPtr(viewPtr));
viewPtr->setControlller(this);
}
Oddly enough problem two wasn't crashing the program until I fixed another problem that was crashing the program. What's wrong with my code?
Keep in mind that wxWidgets does its own form of memory management for widgets. So if you are dynamically allocating the memory for a widget-type, and you then pass the address of that widget to an object that can call delete on it while the parent of that widget is designated by the wxWidgets run-time to destroy that widget when the parent widget is destroyed, then you're going to run into a case of double-deletion, or a case where the parent still thinks the child widget is a valid object when it's not. A shared-pointer type will basically "own" an object ... so make sure that when you dynamically allocate an object and pass it to a shared-pointer type that you are not inadvertently making the pointer "owned" by two different memory-reclaiming pathways.