tags:

views:

58

answers:

1

I'm currently writing a set of wrapper functions of Qt4 for an application as plugin (because I personally think that writing extensions in plain C is easier to accomplish).

At first I though this could be done by simply abstracting the following:

#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
    QApplication* app = new QApplication(argc, argv);
    QPushButton* hello = new QPushButton("Hello world!");
    hello->resize(500, 300);
    hello->show();
    return app->exec();
}

Into this (as a matter of fact, that's the code in main.c of my wrapper):

#include "bind.h"

int main(int argc, char* argv[])
{
    gui_application_t* app;
    gui_pushbutton_t* hello;
    app = gui_application_new(argc, argv);
    hello = gui_pushbutton_new("Hello World");
    gui_pushbutton_resize(hello, 100, 30);
    gui_pushbutton_show(hello);
    return gui_application_exec(app);
}

While the former works (as expected), I'm getting segmentation faults at apparently random places in the latter. I hoped my version would just do the same as the former... but I'm afraid it doesn't at all :-(

After running the binary, the output is usually:

 *** GUI Debug: gui_application_new: ctx->app = hex_addr
 *** GUI Debug: gui_pushbutton_new: ctx->button = hex_addr
 *** GUI Debug: gui_pushbutton_resize: ctx->button = hex_addr
 *** GUI Debug: gui_pushbutton_show: ctx->button = hex_addr
Segmentation fault

However, even after removing the calls to gui_pushbutton_* (and only calling gui_application_new and gui_application_exec), the application will still crash, but in gui_application_exec.

Output from running the binary with gdb: http://codepad.org/wBifH1B2

Sources: http://dl.dropbox.com/u/863332/wrapper.tar.bz2

Any help is very appreciated, as this got me very puzzled...

A: 

A call to gui_allocate:

ctx = gui_allocate<gui_pushbutton_t>(sizeof(gui_pushbutton_t*));

suggests that the function works like malloc and takes a requested size and returns an address to a buffer of that size, but that is not the case. This is a template-ed function, and each version of it knows the type. It is really more like calloc than malloc because the call:

ctx = gui_allocate<gui_pushbutton_t>(1);

would allocate enough space for one gui_pushbutton_t. gui_allocate's parameter is an array length, not an element size.

You were allocating an array of them with length sizeof(gui_pushbutton_t *).

I don't really see how that would cause segmentation faults since it should result in a larger memory than needed being allocated, unless it is either the constructor or some other action on behalf of these excess array members that is causing your problem.

nategoose
the segmentation fault does not occur in the call to gui_allocate -- however, gui_allocate in general is a bad habit of mine. I could also just have written `gui_pushbutton_t* ctx = new gui_pushbutton_t;` which would do exactly the same thing... in a more sane way.
nebukadnezzar
I've modified the sources to meet what you've pointed out.
nebukadnezzar
The segfault happens in `strlen` (__strlen_sse2) called by `int XSetCommand(Display *d, Window w, char * argv, int argc)`. Try writing `size_t __strlen_sse2(const char *s) { size_t z = 0; while(*(s+z)) {z++} return z;}` in your `main.c` and set a break point in there and see what that is being passed. You may have to play around with the name (using regular `strlen` or `__strlen`) to get it to use your version.
nategoose
@nategoose I'm not sure what you mean, there are no strlen calls in any of the sourcefiles.
nebukadnezzar
@nebukadnezzar: The gdb output you gave said that it was in a strlen call when the failure occurred. This call was made within a library function (not directly by your code). In fact, it was about 6 or 7 calls deep in library code. By replacing strlen with a version in your source I was hoping that it would be easier for you to see what it was passed in gdb when it failed, maybe yielding a clue.
nategoose
@nategoose: I see. However, even though I managed to eradicate the segmentation fault by using a different approach, I still see no GUI, so I decided to use a different Library (most likely FLTK).
nebukadnezzar