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.
Related
I am trying to learn how to use gtkmm having got a basic grasp of C++ (I like a challenge!). I have been working my way through the tutorials (as well as other reading). I am trying to use the approach of using glade to design the UI and then write the code to do the work.
So I have built a very simple UI (window and button at the moment!). I am using the GTK::Builder to load the UI from file. I am dividing the code into classes and a main caller.
Here is the main.cpp
#include "hellowindow.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[]) {
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example"); //creates a Gtk::Application object, stored in a Glib::RefPtr smartpointer, create() method for this object initializes gtkmm.
HelloWindow hw; // Create a HelloWindow object
return app->run(hw, argc, argv); // shows the HelloWindow object and enter the gtkmm main processing loop, will then return with an appropriate success or error code
}
here is the header for the HelloWindow class
#ifndef HELLOWINDOW_H
#define HELLOWINDOW_H
#include <gtkmm/application.h>
#include <gtkmm/applicationwindow.h>
#include <gtkmm/button.h>
#include <gtkmm/box.h>
#include <gtkmm/builder.h>
#include <glibmm/fileutils.h>
/* derive the class from Gtk::ApplicationWindow base class */
class HelloWindow : public Gtk::ApplicationWindow {
public:
/* Conctructor */
HelloWindow();
/* Destructor */
~HelloWindow() override;
protected:
/* Signal handlers: */
void on_button_clicked();
/* Member widgets: */
Gtk::Box *cont; // Container
Gtk::Button *pButton; // Pointer to a Button
Glib::RefPtr<Gtk::Button> display_btn; // Smart pointer to a Button
Glib::RefPtr<Gtk::Builder> builder; // Builder
};
#endif // HELLOWINDOW_H
and here is the class code:
#include "hellowindow.h"
#include <iostream>
HelloWindow::HelloWindow() : builder(Gtk::Builder::create()){
try {
/* load window from glade file */
builder->add_from_file("glade/simple.glade");
}
catch(const Glib::FileError& ex) {
/* catch file errors */
std::cerr << "FileError: " << ex.what() << std::endl;
return;
}
/* ui builder created successfully from file */
/* add a container to the builder */
builder->get_widget<Gtk::Box>("cont", cont);
builder->get_widget<Gtk::Button>("display_button", pButton);
pButton->signal_clicked().connect(
sigc::mem_fun(*this, &HelloWindow::on_button_clicked)
);
/* add the container to the application window */
add(*cont);
/* set some parameters for the window */
set_title("Simple Gtk::Builder Demo"); // set the window title
set_default_size(500, 500); // set the window size
show_all(); // show the window and all of the enclosed widgets
}
HelloWindow::~HelloWindow(){
}
void HelloWindow::on_button_clicked(){
std::cout << "Hello World" << std::endl;
}
This all works fine and I think I understand what is happening. However, I have seen a different approach to adding widgets at runtime (https://sodocumentation.net/gtk3/topic/5579/using-glade-with-builder-api). The difference is how the button object is declared. In the code above it is declared as a pointer to a button object in the line:
builder->get_widget<Gtk::Button>("display_button", pButton);
However, the website above uses an approach of a smartpointer to the button object:
display_btn = Glib::RefPtr<Gtk::Button>::cast_dynamic(builder->get_object("display_button"));
The second way of doing it seems less clear, specifically the cast_dynamic aspect, would someone please explain the difference between the two approaches?
I hope that I have included enough information.
Thank you
Martyn
First of all, to understand the difference, and since you are new to
C++, I would recommend reading on the following topics:
Dynamic memory allocation (new/delete)
Memory leaks
Casting
Templates
First approach: get_widget
With this approach, you are getting a raw pointer (as opposed to a smart
pointer) to a widget defined from the ui file. Example:
Gtk::Grid* pGrid = nullptr;
refXml->get_widget("mygrid", pGrid);
After this, pGrid points to a Gtk::Grid widget. Notice that no
casting is required, you immediately get a Gtk::Grid. This is because
the Gtk::Builder::get_widget method is a template method:
// T_Widget is like a placeholder for some widget type,
// like Gtk::Grid for example.
template <class T_Widget >
void Gtk::Builder::get_widget(const Glib::ustring& name,
T_Widget*& widget
)
Usually in C++, such
raw pointers may be dangerous because if they point to an object
allocated on the heap (usually using new), one must remember to use
delete on them when done, otherwise memory leaks will occur. In this
case, pGrid is indeed a raw pointer to an object allocated on the
heap, but the documentation states:
Note that you are responsible for deleting top-level widgets (windows
and dialogs) instantiated by the Builder object. Other widgets are
instantiated as managed so they will be deleted automatically if you
add them to a container widget.
so most of the time (i.e. if not a toplevel widget), you do not have
to call delete, but sometimes you do. This is because Gtkmm has facilities
to automatically delete destroyed objects. See Gtk::manage for
more information on this.
When or not to use delete may become hard as code grows, especially since
you do not have to always do it (it can become easy to forget).
Second approach: get_object
With this approach, you are getting a smart pointer (a Glib::RefPtr) to
an object and casting to the right type is required, hence the
cast_dynamic
// get_object returns a Glib::RefPtr<Glib::Object>, which is not a Glib::RefPtr<Gtk::Button>
// so a cast is performed. This works because Gtk::Button is a child class of
// Glib::Object.
display_btn = Glib::RefPtr<Gtk::Button>::cast_dynamic(builder->get_object("display_button"));
The advantage of this is that once the cast is performed,
you do not have to manage the object's memory. It is managed by the
smart pointer (i.e. the smart pointer will automatically call delete
for you. This is true even for "top level" widgets.
Note: the cast used here, cast_dynamic, is a Gtkmm specific cast which wraps a dynamic_cast.
My opinion
I would personally go with the second approach because you get automatic
memory management (even for top level widgets), and hence no memory leaks.
However, the code gets harder to read as you already noticed.
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 am making a client server application, with the server having a GUI. I am using Qt.
For communication I am using pipes.
I have divided the server application into a backend, and a GUI. The backend has a PipeServer class, and in the GUI, I have overriden functions like onReceiveMessage etc.
Everything worked fine until I decided to add a std::queue as a base class member.
At the start of the application, I get an exception, and upon inspection it seems that my queue does not start with 0 elements. In fact it seems like the queue is not initialized at all. There are 2 possibilites: it could be because I the GUI class inherits 2 classes, and somehow the second base class, which is my PipeServer does not properly initialize its members, or it could be because the pipeServerGUI object is moved to a different thread by QT.
Any ideas on how I could solve this?
Relevant code:
class HookServer
{
PIPEINST Pipe[INSTANCES];
HANDLE hEvents[INSTANCES];
VOID DisconnectAndReconnect(DWORD);
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED);
VOID GetAnswerToRequest(LPPIPEINST);
public:
std::queue<std::string> messages;
int init(std::string pipename);
int run();
virtual void onNewConnection() {};
virtual void onReceiveMessage(std::string message) {};
};
class HookServerGUI : public QObject, public HookServer
{
Q_OBJECT
void onReceiveMessage(std::string message);
void onNewConnection();
public slots:
void doWork() {
init("\\\\.\\pipe\\hookpipe");
run();
}
signals:
void signalGUI(QString message);
};
//GUIServerCreation
QThread *thread = new QThread;
HookServerGUI* worker = new HookServerGUI;
QObject::connect(worker,SIGNAL(signalGUI(const QString&)),this,SLOT(processMessage(const QString&)));
worker->moveToThread(thread);
thread->start();
QMetaObject::invokeMethod(worker, "doWork", Qt::QueuedConnection);
EDIT:
The exception is a access violation exception. It happens in this part of code:
VOID HookServer::GetAnswerToRequest(LPPIPEINST pipe)
{
onReceiveMessage(pipe->chRequest);
if(!messages.empty())
{
std::string s = messages.front();
messages.pop();
strcpy(pipe->chReply,s.c_str());
pipe->cbToWrite = strlen(s.c_str()+1);
}
}
Since messages.empty() return some huge number, it tries to read the first object and somehow fails.
There is also no PipeServerGUI constructor.
EDIT2:
I solved part of this problem by placing parenthesis after new HookServerGUI();
The problem is that still the function does not work, and throws a access violation exception. It happens on the front() line. When checked in a debugger, the function does have 1 element, so it is not because it is empty. Any ideas?
EDIT3:
With the second run, unfortunately the queue.size() is still incorrect. Seems like a data race to me.
The problems are in the code that you don't show, and it's a classic case of a memory bug, it looks like. Some code somewhere is writing on memory it doesn't own. Probably you have a bug in the way you use winapi. You need to create a minimal, self-contained test case.
I think you might be shooting yourself in the foot by not using QLocalSocket: on Windows, it's a named pipe - exactly what you want.
Besides, this is C++ code. There is no reason at all to put either PIPEINST or HANDLE into a raw C array. Use QVector or std::vector. Probably the rest of the code is full of C-isms like that, and something somewhere goes wrong.
I wouldn't discount a buffer overrun, since obviously you are ignoring the size of the buffer in PIPEINST from the - the strcpy can overrun the buffer. I'm also not sure that PIPEINST from the example code is using the same character type as what std::string::c_str() is returning.
Even if you wanted to implement your code using explicit pipes without QLocalSocket, you should still use C++, QString etc. and understand what's going on with your data.
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.
I was working for a while with different C++ GUI frameworks (e.g. Qt, wxWidgets, also some proprietary) but cannot decide for myself regarding the topic described below.
As discussed in several questions/answers here, direct use of delete this is valid in C++ (as long as you don't dereference this any more), but it is in most cases not good idea.
But in some cases, object invokes its destructor indirectly. This situation specifically often arise in event drive systems (GUI applications come to mind first).
class Kernel {
public:
void Start() {
_window = new Window();
}
void OnCloseButton() {
if (_window) {
_window->Close();
delete _window;
_window = NULL;
}
private:
MyWindow * _window;
};
class MyWindow
{
public:
MyWindow(Kernel & kernel) : _kernel(&kernel) {
Connect(my_button_close_event, this, OnCloseButtonClicked);
}
OnCloseButtonClicked() {
// This call actually calls destructor of this object.
_kernel->OnCloseButton();
// If we access any fields of Window here, we're going to have problems
}
private:
Kernel * _kernel;
};
Notice: I did not try to compile the code - it may have typos or bad practices. But it should illustrate the idea.
So, the question is: Is it OK to do something like in the example above: the handler of the event calls some other function (method of its owner), which indirectly deletes this?
Or should I better make the Kernel class event aware and connect the event from the button directly to the method in the Kernel and then we do not have this situation of indirect call to delete this.
Thanks in advance.
It's possible to do so since the Window instance is created by the Start() method but it's a bad practice in Object Oriented Programming.