Qt Qstring <not accessible =“”>和SIGSEGV segmantation fault

时间:2015-07-21 15:01:36

标签: c++ qt

从GET_STATION_MODEL_PARAMS_t访问QString类型的struct成员时,我看到一个奇怪的分段错误。执行在**停止执行:

代码:

#include <QDebug>
#include "hradcontroller.h"
#include "hradAPI.h"

#define TAG "HRAD_CONTROLLER:\0"
#define HRAD_API_VERSION        "2"
#define MANUFACTURER_KEY        "abcde12345"

typedef struct registerDeviceParams{
    QString brand; 
    QString device;
    QString manufacturer;
    QString model;
    QString serial;
    QString ibd; 
    QString ibkey;
    QString version;
    QString track;

    registerDeviceCB_t cbFn;
}REGISTER_DEVICE_PARAMS_t;

typedef struct getStationModelParams{
    int stationID;
    QString ibd;
    QString ibkey;
    QString version;
    QString track;

    getStationModelCB_t cbFn;

    GET_STATION_MODEL_RESPONSE_t* resp;
 }GET_STATION_MODEL_PARAMS_t;

HRAD *hbr = new HRAD();

void registerDevice(){
    REGISTER_DEVICE_PARAMS_t params;
    params.brand = "brand";
    params.device = "TI-J6";
    params.manufacturer = "manuf";
    params.model = "EVK";
    params.ibkey = MANUFACTURER_KEY;
    params.serial = "abcde12345";
    params.version = HRAD_API_VERSION;
    params.track = "true";
    params.cbFn = deviceRegisteredCB;

    hbr->registerDevice(&params);
}

 void getStationModel(int id){
    GET_STATION_MODEL_PARAMS_t params;
    params.stationID = id;
    params.ibd = hbr->getId();
    params.ibkey = "abdef";
    params.version = "2";
**  params.track = "false";  //SIGSEGV segmantation fault here
    params.cbFn = stationModelAvailableCB;

    params.resp = &g_StationModel;
}

void deviceRegisteredCB(QString ibd){
    qDebug() << TAG << "Device Registered: ibd = " << ibd;

    getStationModel(currentPublicStationID);
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    /* Register ourselves to HRAD Server */

    registerDevice();
}

在seg之前的值。故障:

enter image description here

如果您在调试时发现“track”“无法访问”,则会导致崩溃。

我修改了GET_STATION_MODEL_PARAMS_t:

typedef struct getStationModelParams{
    int stationID;
    QString foo; //dummy variable.
    QString ibd;
    QString ibkey;
    QString version; //seg. fault here now
    QString track;

    getStationModelCB_t cbFn;

    GET_STATION_MODEL_RESPONSE_t* resp;
 }GET_STATION_MODEL_PARAMS_t;

价值观变得像这样: enter image description here

现在“版本”也“无法访问”。

知道为什么会这样吗?

感谢。

更新1:

工具:

Qt Creator 3.4.1(ubuntu 14.04)

Qt 5.4.2(GCC 4.6.1,64 bit)

1 个答案:

答案 0 :(得分:2)

TL; DR:这就是为什么你真的需要发布重现崩溃所需的所有代码。

您的代码有效 - 没有崩溃。因此,即使答案对您和其他所有人都完全无用,您的问题也会得到解答。 请勿提出只能以无法帮助您的方式回答的问题。

在你的代码中唯一突出的是,除了它是现代C ++中没有位置的可怕的C憎恶之外,HRAD实例是在main开始执行之前创建的。根据HRAD构造函数的作用,这可能是一件坏事。

但是,让我们看看我们是否可以修改一些代码,以指导您编写更安全的代码。

旧代码

首先,让我们逐字地开始您的代码,在开头和结尾添加一些内容以使其编译和执行。

你应该在你的问题中提供所有这些 - 足够的&#34;其他东西&#34;崩溃。以下,假设它崩溃或以其他方式重现您的问题,将被视为sscce,并使您的问题对社区有价值。

#include <QString>
#include <QDebug>

typedef void (*registerDeviceCB_t)(QString);
typedef void (*getStationModelCB_t)();
typedef struct getStationModelResponse {} GET_STATION_MODEL_RESPONSE_t;
void deviceRegisteredCB(QString);
void stationModelAvailableCB() {}

typedef struct registerDeviceParams REGISTER_DEVICE_PARAMS_t;
struct HRAD {
   void registerDevice(REGISTER_DEVICE_PARAMS_t*);
   QString getId() { return QString(); }
};

GET_STATION_MODEL_RESPONSE_t g_StationModel;
int currentPublicStationID = 1;

void registerDevice();
void getStationModel(int);
int main()
{
   registerDevice();
   getStationModel(0);
   return 0;
}

// Your code verbatim beyond this point

您的代码,复制粘贴以供参考(显然不相关MainWindow已移除):

#define TAG "HRAD_CONTROLLER:\0"
#define HRAD_API_VERSION        "2"
#define MANUFACTURER_KEY        "abcde12345"

typedef struct registerDeviceParams{
   QString brand;
   QString device;
   QString manufacturer;
   QString model;
   QString serial;
   QString ibd;
   QString ibkey;
   QString version;
   QString track;

   registerDeviceCB_t cbFn;
}REGISTER_DEVICE_PARAMS_t;

typedef struct getStationModelParams{
   int stationID;
   QString ibd;
   QString ibkey;
   QString version;
   QString track;

   getStationModelCB_t cbFn;

   GET_STATION_MODEL_RESPONSE_t* resp;
}GET_STATION_MODEL_PARAMS_t;

HRAD *hbr = new HRAD();

void registerDevice(){
   REGISTER_DEVICE_PARAMS_t params;
   params.brand = "brand";
   params.device = "TI-J6";
   params.manufacturer = "manuf";
   params.model = "EVK";
   params.ibkey = MANUFACTURER_KEY;
   params.serial = "abcde12345";
   params.version = HRAD_API_VERSION;
   params.track = "true";
   params.cbFn = deviceRegisteredCB;

   hbr->registerDevice(&params);
}

void getStationModel(int id){
   GET_STATION_MODEL_PARAMS_t params;
   params.stationID = id;
   params.ibd = hbr->getId();
   params.ibkey = "abdef";
   params.version = "2";
   params.track = "false";  //SIGSEGV segmantation fault here
   params.cbFn = stationModelAvailableCB;

   params.resp = &g_StationModel;
}

void deviceRegisteredCB(QString ibd){
   qDebug() << TAG << "Device Registered: ibd = " << ibd;

   getStationModel(currentPublicStationID);
}

// End of verbatim code

最后,registerDevice

的实施
void HRAD::registerDevice(REGISTER_DEVICE_PARAMS_t* params) {
   params->cbFn("some ibd");
}

这三个部分放入main.cpp后,将编译,运行并正确调用回调。即:

Starting bad-c-aargh-31542746...
HRAD_CONTROLLER: Device Registered: ibd =  "some ibd"
bad-c-aargh-31542746 exited with code 0

返修

您似乎正在使用回调并通过指针传递值,就像在C中一样。我们将摆脱C ++中不必要的C类型dede,我们将利用C ++ 11& #39; s使回调更有用的功能。

如上所述,下面的代码只是穿插评论。您可以将其复制粘贴到main.cpp,删除注释,编译并运行。它已经完成了。

首先,让我们包含functional标题以引入std::function,我们将摆脱C风格的宏:

#include <QString>
#include <QDebug>
#include <functional>

const QString TAG = QStringLiteral("HRAD_CONTROLLER:");
const QString HRAD_API_VERSION = QStringLiteral("2");
const QString MANUFACTURER_KEY = QStringLiteral("abcde12345");

然后我们将定义用于将参数传递给HRAD方法的结构,并从这些方法中获取响应:

struct RegisterDeviceParams {
   QString brand;
   QString device;
   QString manufacturer;
   QString model;
   QString serial;
   QString ibd;
   QString ibkey;
   QString version;
   QString track;
};

struct GetStationModelParams {
   int stationID;
   QString ibd;
   QString ibkey;
   QString version;
   QString track;
};

struct GetStationModelReponse {};

然后我们可以实现一个骨架HRAD类。参数作为const引用传递。 可选回调可以是兼容的lambdas,functor实例,函数指针等。提供默认构造的值使它们成为可选的。您可以将它们从调用中删除,编译器将使用默认值。 currentPublicStationID,可能是一个全局变量,也属于HRAD

class HRAD {
public:
   void registerDevice(const RegisterDeviceParams &,
                       const std::function<void(const QString & ibd)> & cb
                       = std::function<void(const QString&)>()) {
      cb("some ibd");
   }

   void getStationModel(const GetStationModelParams &,
                        const std::function<void(const GetStationModelReponse &)> & cb
                        = std::function<void(const GetStationModelReponse&)>()) {
      GetStationModelReponse response;
      cb(response);
   }

   QString getId() { return "some id"; }
   int currentPublicStationID;
   HRAD() : currentPublicStationID(1) {}
};

使用HRAD宏定义Q_GLOBAL_STATIC的全局实例。首次使用时,它将被线程安全地实例化。它充当指针 - 获取全局实例,您应该使用->运算符。

Q_GLOBAL_STATIC(HRAD, hbr) // no semicolon needed

getStationModelregisterDevice函数将使用lambda语法在现场实例化回调。当然,如果回调更复杂,您可以将它们放在独立的函数或方法中。

void getStationModel(int id){
   GetStationModelParams params;
   params.stationID = id;
   params.ibd = hbr->getId();
   params.ibkey = "abdef";
   params.version = "2";
   params.track = "false";

   hbr->getStationModel(params, [](const GetStationModelReponse&){
      qDebug() << "got station model";
   });
}

void registerDevice(){
   RegisterDeviceParams params;
   params.brand = "brand";
   params.device = "TI-J6";
   params.manufacturer = "manuf";
   params.model = "EVK";
   params.ibkey = MANUFACTURER_KEY;
   params.serial = "abcde12345";
   params.version = HRAD_API_VERSION;
   params.track = "true";

   hbr->registerDevice(params, [](const QString & ibd){
      qDebug() << TAG << "Device Registered: ibd = " << ibd;
      getStationModel(hbr->currentPublicStationID);
   });
}

最后,我们从main:

调用registerDevice
int main()
{
   registerDevice();
   return 0;
}

此代码有效,并产生以下输出:

Starting bad-c-aargh-31542746...
"HRAD_CONTROLLER:" Device Registered: ibd =  "some ibd"
got station model
bad-c-aargh-31542746 exited with code 0

请注意,没有任何手动内存管理。原始指针既不作为参数也不作为成员使用。