Qt c++的分段故障

Segfault with Qt C++

本文关键字:故障 分段 c++ Qt      更新时间:2023-10-16

我的代码崩溃与段错误,我不能真正弄清楚错误在哪里。我还在学习指针作为参数传递的方法。下面是与此相关的代码。运行issueBook()功能时出现段故障

IssuedBooks.h

#ifndef ISSUEDBOOKS_H
#define ISSUEDBOOKS_H
#include "ClientList.h"
#include "BookList.h"
#include <QMultiMap>
class IssuedBooks {
public:
    IssuedBooks() {}
    ~IssuedBooks();
    void issueBook(Client*, Book*);
    void returnBook(Client*, Book*);
    ClientList getClients() const;
    BookList getClientBooks(Client*) const;
private:
    QMultiMap<Client*, Book*> issuedBooks;
};
#endif

IssuedBooks.cpp

#include "IssuedBooks.h"
#include <qDebug>
IssuedBooks::~IssuedBooks(){
    qDeleteAll(issuedBooks);
    issuedBooks.clear();
}
void IssuedBooks::issueBook(Client* c, Book* b){
     if(!issuedBooks.contains(c, b)){
        issuedBooks.insert(c, b);
     }
}
void IssuedBooks::returnBook(Client* c, Book* b){
    if(issuedBooks.contains(c, b)){
        issuedBooks.remove(c, b);
    }
}
ClientList IssuedBooks::getClients() const{
    QMapIterator<Client*, Book*> itr(issuedBooks);
    ClientList clients;
    while(itr.hasNext()){
        itr.next();
        clients.addClient(itr.key());
    }
    return clients;
}
BookList IssuedBooks::getClientBooks(Client* c) const{
    QMapIterator<Client*, Book*> itr(issuedBooks);
    BookList books;
    while(itr.hasNext()){
        itr.next();
        if(itr.key() == c){
            books.addBook(itr.value());
        }
    }
    return books;
}

LibraryDriver.cpp

#include "ClientList.h"
#include "BookList.h"
#include "IssuedBooks.h"
#include <QtGui>
#include <QtWidgets>
QTextStream cout(stdout);
int main(int argc, char* argv[]){
    QApplication app(argc, argv);
    BookList bookList;
    ClientList clientList;
    IssuedBooks issueList;
    Book* b = new Book("Nick Corin", "An awesome life.", 59.99);
    bookList.addBook(b);
    Client* c = new Client("Nick Corin", QDate::currentDate());
    clientList.addClient(c);
    issueList.issueBook(c, b);
}

这类问题在您的编程生活中会经常遇到,所以这里有一个通用的解决方案:

  1. 你应该试着找出区段故障发生的确切位置。我假设您正在使用GCC/GNU开发工具链。因此,您要做的第一件事是使用-g标志编译代码,该标志包括二进制文件中的调试符号。如果您使用的是IDE,那么当您选择"Debug"作为构建类型时就会发生这种情况。如果您自己调用g++,请将-g添加到g++选项中。
  2. 在gdb中加载程序,GNU DeBugger: gdb --args yourprogram yourprogramarguments .
  3. 运行:(gdb) run<enter>
  4. 等待段故障。
  5. 使用backtrace命令查找区段故障发生的位置

还有很多其他有用的gdb命令可以让您print变量,或者就地修改它们。通常,您希望添加breakpoint s;help <commandname>将打印一些帮助。

我为GNU Radio开发人员编写了一个更全面的指南,但它也适用于这里:使用GDB调试

对于初学者来说,最常见的错误是尝试使用尚未创建和初始化的对象。由于变量中的内存指针指向随机地址或null,因此会产生内存访问错误(segfault)。

"在计算中,段错误(通常简称为段错误)或访问冲突是由具有内存保护的硬件引起的错误,通知操作系统(OS)内存访问冲突"

issueBook()函数包含一个未初始化的强候选变量。