PDA

View Full Version : Segmentation Fault When Moving QTextCursor Anchor



PrincessTrevor
7th June 2021, 05:40
First time making a program with a GUI, using c++. I have a QTextBrowser that I want to use to provide the user with a text file of lines that they can select, then insert a new line either before or after the selected line. I'm setting up the line-by-line selection using these:


connect(ListWindow, &QTextBrowser::cursorPositionChanged, this, &MainWindow::handleSelect);

and


void MainWindow::handleSelect(){
ListWindow->moveCursor(QTextCursor::StartOfLine); //move cursor and anchor to start of line
ListWindow->moveCursor(QTextCursor::EndOfLine, QTextCursor::KeepAnchor); //move cursor to end of line without anchor, selecting text between
}

When I click a line in the browser, I get this:
"The inferior stopped because it received a signal from the operating system.
Signal name: SIGSEGV
Signal meaning: Segmentation fault"

Each line in handleSelect works on its own, the program only crashes when I run both. What do I need to do to avoid this?

d_stranz
7th June 2021, 15:16
A segmentation fault usually happens when you try to use an uninitialized pointer, a pointer that has been deleted, or a null pointer. Since you don't show any more than a few lines of code, it is impossible to tell where this might be happening. What is "ListWindow" and how do you create, initialize, and use it? Is it still in scope and valid when this slot is called?

PrincessTrevor
7th June 2021, 17:03
Here's the full code:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTextBrowser>
#include <QPushButton>
#include <QMouseEvent>
#include <QTextCursor>
#include <QTextDocumentFragment>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:
void handleInsert();
void handleSelect();
private:
Ui::MainWindow *ui;

QPushButton *ButtonInsert;
QTextBrowser *ListWindow;
};

#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

MainWindow w;
w.show();
return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ButtonInsert = new QPushButton("Insert", this);
ButtonInsert -> setGeometry(QRect(QPoint(440,90), QSize(100,30)));

ListWindow = new QTextBrowser(this);
ListWindow -> setGeometry(QRect(QPoint(50,50), QSize(300,500)));
ListWindow -> setText("This is a test");

connect(ListWindow, &QTextBrowser::cursorPositionChanged, this, &MainWindow::handleSelect);
connect(ButtonInsert, &QPushButton::released, this, &MainWindow::handleInsert);
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::handleInsert(){
//test code for learning
ButtonInsert->setText("Inserting...");
ButtonInsert->setText("Inserted");
}

void MainWindow::handleSelect(){
ListWindow->moveCursor(QTextCursor::StartOfLine);
ListWindow->moveCursor(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
}

ChristianEhrlicher
7th June 2021, 17:27
You create an infinite loop since you modify the cursor position inside a slot which gets called when the cursor position changes.

PrincessTrevor
7th June 2021, 17:46
"I'd considered that, but then why would each of these lines work individually without creating an infinite loop, but not together? "

...is what I would've said last night. Just thought about it more, each line moves the cursor to the beginning or end, which calls the function again, but it doesn't move the second time since it's already at its destination. With that being the case, do you have any recommendations for what I could do to achieve this effect? Looking through the signals for TextEdit and Browser I don't see anything that would help me here.

ChristianEhrlicher
7th June 2021, 18:10
I don't understand what you're trying to achieve at all. Why first move it to the front, then to the end and all this inside a slot which is called when the cursor position changes? It's just pointless.

PrincessTrevor
7th June 2021, 18:37
Not "pointless" for the use of the project. The goal is to select the line the user clicks on. The intent was that when they click, the cursor moves to that line, setting off the cursor move slot. Then pull the anchor to the beginning of the line and then move the cursor alone to the end of the line, which will select it. Obviously the infinite loop wasn't intended, which is why I'm trying to find a better way to do this, which will likely involve not having this process inside the cursorPositionChanged slot but I don't see another way to do it. Odds are I'm just missing something, never worked with QT before.

ChristianEhrlicher
7th June 2021, 19:22
Your idea is fine but which connect to cursorPositionChanged then? I mean - how should a user change the cursor at all then?

PrincessTrevor
7th June 2021, 20:49
The user moves the cursor by clicking. In any case, I fixed the issue by changing handleSelect to this:


void MainWindow::handleSelect(){
if (ListWindow->textCursor().atBlockEnd() == false){
ListWindow->moveCursor(QTextCursor::StartOfLine);
ListWindow->moveCursor(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
}
}

Works fine for test cases, should be fine moving forward. Thanks for the help.