Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[SOLVED] My simple QAbstractTableModel is crashing



  • Hi,

    I'm struggled with simple QAbstractTableModel all day. Can anyone tell me why it is crashing with SIGSEGV error? Am I blind or something? Error occur after call PluginsModel::add. Here is also compilable demo, press button and application should crash:
    http://ubuntuone.com/5IYswvjytWyvw7ktliV1Fv

    @class Plugin: public QObject
    {
    Q_OBJECT

    public:
    explicit Plugin(QObject *parent=0);
    ~Plugin();

    const QString title();
    void setTitle(const QString &s);
    

    private:
    QString mTitle;
    };

    class PluginsModel: public QAbstractTableModel
    {
    Q_OBJECT

    public:
    explicit PluginsModel(QObject *parent=0);
    ~PluginsModel();

    int columnCount(const QModelIndex &parent) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
    
    void clear();
    const QString add(const QString &title);
    

    private:
    QList<Plugin *> mItems;
    };

    Plugin::Plugin(QObject *parent) : QObject(parent)
    {

    }

    Plugin::~Plugin()
    {

    }

    const QString Plugin::title()
    {
    return mTitle;
    }

    void Plugin::setTitle(const QString &s)
    {
    mTitle = s;
    }

    PluginsModel::PluginsModel(QObject *parent) : QAbstractTableModel(parent)
    {

    }

    PluginsModel::~PluginsModel()
    {
    clear();
    }

    int PluginsModel::columnCount(const QModelIndex &parent) const
    {
    Q_UNUSED(parent);
    return 1;
    }

    int PluginsModel::rowCount(const QModelIndex &parent) const
    {
    Q_UNUSED(parent);
    return mItems.count();
    }

    QVariant PluginsModel::data(const QModelIndex &index, int role) const
    {
    if (!index.isValid())
    return QVariant();

    if (index.row() >= mItems.count() || index.row() < 0)
        return QVariant();
    
    if (role == Qt::DisplayRole) {
        return mItems.at(index.row())->title();
    }
    return QVariant();
    

    }

    QVariant PluginsModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
    if (role == Qt::DisplayRole) {
    switch (section) {
    case 0:
    return "Title";
    break;
    default:
    break;
    }
    }
    return QVariant();
    }

    void PluginsModel::clear()
    {
    beginResetModel();
    qDeleteAll(mItems);
    mItems.clear();
    endResetModel();
    }

    const QString PluginsModel::add(const QString &title)
    {
    beginInsertRows(QModelIndex(), mItems.count(), mItems.count());
    Plugin *p = new Plugin(this);
    p->setTitle(title);
    mItems.append(p);
    endInsertRows();
    }@


  • Lifetime Qt Champion

    Hi,

    Aren't you inserting too much rows in your add function ?



  • What do you mean? I'm just adding one: mItems.append(p)


  • Lifetime Qt Champion

    Sorry, I misread your code.

    You ignored an important warning: you are not returning anything from your add function



  • Wow... that was it. Finally can sleep! I'm just learning C++. I'm old Free Pascal programmer, this is something new for me that application is crashing because function doesn't return anything. Well, I'm understand that this is syntax issue but this is impossible to debug. I just need new habits when analyzing code.
    P.S.: Why compiler is compiling this code? This is not warning. Warnings can be ignored but in this case not, function just never will work. Can't understand this...


  • Lifetime Qt Champion

    You declared your function with a QString return value thus not returning anything is considered "Undefined behavior" so for e.g. int you'll probably get a funky number, but for more complex classes the result can be worse, in your case a crash.

    If you don't need that string (and it looks like you don't) just make the function void and remove the return statement.



  • Yes in final stage I'll need string result, but for now don't, so I forgot about "return". I didn't expect that this one line will crash all my application. It's probably my fault, I thought that C++ "return" is working in similar way as pascal "result". I don't want to start programming language fight, but in Free Pascal if you don't declare result in function then you will also get compiler warning but nothing strange will happen if you don't use function result (don't cast random returned integer into pointer etc.). In C++ if you don't call "return" in function then your application will always crash even if result value is used or not. So what is a sense marking this syntax as warning betweens real warnings which can be ignored? It should be blocked at compiling time. This thing blowed my mind today.


  • Lifetime Qt Champion

    IIRC, not all compilers react the same way to that one. I have been bitten by this error exactly while using code not written by me. The thing it taught me is to watch out for warnings...


Log in to reply