Ошибка сегментации при доступе к закрытой переменной класса - PullRequest
0 голосов
/ 27 января 2020

Проблема, с которой я столкнулся, обсуждалась несколько раз, но я до сих пор не понимаю, как решить возникшую проблему. Я много программировал на C ++, но из-за работы переключился на Java. Я возвращаюсь в C ++, и теперь у меня много проблем с управлением памятью / указателями / ссылками и т. Д. c. Эта проблема проистекает из этого.

Для контекста, это файлы для проекта Qt 5.14, над которым я работаю.

Проблема в том, что у меня есть переменная частного класса с именем loggerLevel и метод, который создает ошибку ошибки сегментации - getLevel, которая просто возвращает значение loggerLevel. предполагается для хранения в переменной - это перечисление с именем Level, которое определено в заголовке класса.

Я не знаю, связана ли проблема с моим отсутствием знания или если я неправильно понимаю что-то о том, как классы работают в C ++, или если это что-то совершенно другое. В любом случае, если кто-нибудь может мне помочь, это было бы здорово:)

--- Исходный код ниже ---

logger. cpp

#include "logger.h"

QString debugHTML = "<font color=\"gray\">";
QString infoHTML = "<font color=\"black\">";
QString warningHTML = "<font color=\"yellow\">";
QString errorHTML = "<font color=\"orange\">";
QString criticalHTML = "<font color=\"red\">";
QString endHTML = "</font><br>";

Logger::Logger(QObject *parent,
               QString fileName,
               QTextEdit *editor) : QObject(parent)
{
    m_editor = editor;
    m_showDate = true;
    loggerLevel = Level::INFO;
    if (!fileName.isEmpty()) {
        file = new QFile;
        file->setFileName(fileName);
        file->open(QIODevice::Append | QIODevice::Text);
    }
}

void Logger::write(const QString &value) {

    QString text = value;

    if (m_showDate) {
        text = QDateTime::currentDateTime()
                /*.toString("dd.MM.yyyy hh:mm:ss ") + text;*/
                .toString("hh:mm:ss:  ") + text;
    }

    QTextStream out(file);
    out.setCodec("UTF-8");

    if (file != 0) {
        out << text;
    } else {
        //TODO: add QMessageBox here with error
    }

    //Adds HTML color/formatting
    switch(loggerLevel)
    {
        case DEBUG: text = debugHTML + text; break;
        case INFO: text = infoHTML + text; break;
        case WARNING: text = warningHTML + text; break;
        case ERROR: text = errorHTML + text; break;
        case CRITICAL: text = criticalHTML + text; break;
        default: text = infoHTML + text; break;
    }
    text = text + endHTML;

    if (m_editor != 0) {
        m_editor->insertHtml(text);
    } else {
        //TODO: add QMessageBox here with error
    }
}

void Logger::write(const Level &level, const QString &value) {
    Level prevLoggerLevel = Logger::getLevel();
    Logger::setLevel(level);
    write(value);
    Logger::setLevel(prevLoggerLevel);
}

//--------Setters--------
void Logger::setLevel(const Level &level) {
    loggerLevel = level;
}

void Logger::setShowDateTime(bool value) {
    m_showDate = value;
}


//--------Getters--------
Logger::Level Logger::getLevel() {
    return loggerLevel;
}


Logger::~Logger() {
    if (file != 0) {
        file->close();
    }
}

logger.h

#ifndef LOGGER_H
#define LOGGER_H

#include <QObject>
#include <QPlainTextEdit>
#include <QFile>
#include <QTextStream>
#include <QDateTime>

class Logger : public QObject
{
    Q_OBJECT
public:
    explicit Logger(QObject *parent,
                    QString fileName = 0,
                    QTextEdit *editor = 0);
    ~Logger();
    void setShowDateTime(bool value);
    enum Level
    {
        DEBUG,
        INFO,
        WARNING,
        ERROR,
        CRITICAL
    };

private:
    QFile *file;
    QTextEdit *m_editor;
    bool m_showDate;
    Level loggerLevel;


signals:

public slots:
    void write(const QString &value);
    void write(const Level &level, const QString &value);
    void setLevel(const Level &level);
    Level getLevel();

};

#endif // LOGGER_H

MainWindow. cpp

#include <string>

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "settingsdialog.h"
#include "logger.h"

Logger *logger;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString logFileName = "log.txt";
    Logger *logger = new Logger(this, logFileName, ui->loggerOutput);
    logger->write(Logger::Level::INFO, "Logger Initilized!");
}

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


void MainWindow::on_toolButton_clicked()
{

    SettingsDialog settingsDialog;
    settingsDialog.setModal(true);
    settingsDialog.exec();
}


//Left Side of controller
void MainWindow::on_s_leftJoystickX_Throttle_sliderMoved(int position)
{ ui->l_leftJoystickX->setText(QStringLiteral("X-Axis: %1%").arg(position)); }

void MainWindow::on_s_leftJoystickY_Throttle_sliderMoved(int position)
{ ui->l_leftJoystickY->setText(QStringLiteral("Y-Axis: %1%").arg(position)); }

void MainWindow::on_s_leftTrigger_Throttle_sliderMoved(int position)
{ ui->l_leftTrigger->setText(QStringLiteral("Trigger: %1%").arg(position)); }

void MainWindow::on_s_joystickThrottle_sliderMoved(int position)
{ ui->l_joystickThrottle->setText(QStringLiteral("Throttle: %1%").arg(position)); }


//Right Side of controller
void MainWindow::on_s_rightJoystickX_Throttle_sliderMoved(int position)
{ ui->l_rightJoystickX->setText(QStringLiteral("X-Axis: %1%").arg(position)); }

void MainWindow::on_s_rightJoystickY_Throttle_sliderMoved(int position)
{ ui->l_rightJoystickY->setText(QStringLiteral("Y-Axis: %1%").arg(position)); }

void MainWindow::on_s_rightTrigger_Throttle_sliderMoved(int position)
{ ui->l_rightTrigger->setText(QStringLiteral("Trigger: %1%").arg(position)); }

void MainWindow::on_s_keyboardThrottle_sliderMoved(int position)
{ ui->l_keyboardThrottle->setText(QStringLiteral("Throttle: %1%").arg(position)); }

void MainWindow::on_b_keyboardAction_1_clicked()
{
    logger->write(Logger::Level::CRITICAL, "test");
}

Есть еще файлы, но я считаю, что они не имеют отношения к проблеме, при необходимости я могу опубликовать другие файлы также.

----- Решение! -----

@ churill Решение объясняет, что нужно сделать, чтобы решить эту проблему, но я также буду подробности ниже, чтобы завершить этот вопрос.

Поскольку я уже сделал предварительное объявление logger

Logger *logger

в верхней части MainWindow. cpp, создав новый объект Logger

Logger *logger = new Logger(this, logFileName, ui->loggerOutput);

не требуется, поэтому вызов имени переменной пересылки объявлений вместо создания нового объекта Logger

logger = new Logger(this, logFileName, ui->loggerOutput);

решает проблему!

1 Ответ

2 голосов
/ 27 января 2020

На первый взгляд:

Logger *logger = new Logger(this, logFileName, ui->loggerOutput);

создает объект, который не имеет ничего общего с глобальной переменной logger, которая никогда не инициализируется. Возможно, вы хотели написать только

logger = new Logger(this, logFileName, ui->loggerOutput);

, чтобы инициализировать эту глобальную переменную.


Чтобы несколько ответить на заголовок вашего вопроса: Да, вы на самом деле можете вызвать работает с недопустимыми указателями, но тогда указатель this недопустим, поэтому обращение к переменной-члену вызывает ошибку сегмента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...