0
votes

I used to add a feature in my app based on treewidget.

When right click on an item, I can create a folder on the FS over USB is used.

That mainly say that when selecting an item on the TreeWidget, I get its name and check if it's a folder, if yes, I create a child and add a new folder and file the name.

The make the folder creation done on the FS, I'm using this :

void TreeView::onAddFolderAction() {
    char *parent_folder_name;
    QList<QTreeWidgetItem *> item;
    bool isFolder;

    item = this->selectedItems();
    if (item.empty())
        parent_folder_name = NULL;
    else {
        QString str = item[0]->text(0);
        QByteArray latin_str = str.toLatin1();
        parent_folder_name = latin_str.data();
    }
    setParentFolder(parent_folder_name);

    if(!item.empty())
        isFolder = m_device.isParentFolder(parent_folder_name);
        if(isFolder == false)
            return;

    QTreeWidgetItem* child = new QTreeWidgetItem();
    child->setText(0, "New Folder");
    child->setText(1, "--");
    child->setText(2, "--");
    child->setFlags(child->flags() | Qt::ItemIsEditable);
    if(!item.empty()) {
        item[0]->addChild(child);
        item[0]->setExpanded(true);
    }
    else
        addTopLevelItem(child);

    this->editItem(child);
    this->setCurrentItem(child);
    connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this,  SLOT(onTreeItemChanged()));
    }

this code is connected to a CONNECT when left click action and add folder is selected.

I have done this to avoid the use of a dialog box when renaming. what I'm doing in add an item named New Folder, make it editable and allow the user to change it. when user press enter, the itemChanged signal is triggered and I start onTreeItemChanged.

QList<QTreeWidgetItem *> items;
bool isFolderCreated;
items = this->selectedItems();
QString str = items[0]->text(0);
QByteArray latin_str = str.toLatin1();
char *newFolder = latin_str.data();
char *parent = getParentFolder();

isFolderCreated = m_device.CreateFolder(newFolder, parent);

My issue is that parent do not contain the rigth name.

I'm backuping it in the onAddFolderAction using

setParentFolder(parent_folder_name); 

and get it back using

getParentFolder();

Both are declared as below

void TreeView::setParentFolder(char *name) {
    this->ParentFolder = name;
}

char *TreeView::getParentFolder() {
    return this->ParentFolder;
}

when using the getParent, the value return is not correct. but it seems that what the value is corrupted earlier.

in the on AddFolderACtion(), I had:

   else {
        QString str = item[0]->text(0);
        QByteArray latin_str = str.toLatin1();
        parent_folder_name = latin_str.data();
    }
    setParentFolder(parent_folder_name);

parent_folder_name contain "BLABLA" but when moving step-by-step on setParentFolder, the parent_folder_name change to "XFZV" strange caracters.

Any idea why ?

1
Have you tried using a debugger?user657267
Step 1, read the documentation: "The pointer remains valid as long as the byte array isn't reallocated or destroyed."molbdnilo

1 Answers

5
votes

In the code

else {
    QString str = item[0]->text(0);
    QByteArray latin_str = str.toLatin1();
    parent_folder_name = latin_str.data();
}
setParentFolder(parent_folder_name);

the variable latin_str is local inside the else block, and will go out of scope and get destructed once the else block end. This leaves you with a stray pointer, pointing to now destructed and unallocated memory, leading to undefined behavior when you dereference it.

My recommendation is to use QString as much as possible, and only convert to pointer when actually needed (even if you need to do it multiple times). Either that, or change the rest of the code to accept QString (which would be a better solution IMO).