首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Qstring <not accessible>与SIGSEGV分段故障

Qstring <not accessible>与SIGSEGV分段故障
EN

Stack Overflow用户
提问于 2015-07-21 15:01:35
回答 1查看 1.7K关注 0票数 0

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

代码:

代码语言:javascript
运行
复制
#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之前。过失:

如果注意到“跟踪”在调试时“不可访问”,则会导致崩溃。

我对GET_STATION_MODEL_PARAMS_t做了如下修改:

代码语言:javascript
运行
复制
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;

价值观变成了这样:

现在“版本”也是“不可访问的”。

知道为什么会这样吗?

谢谢。

更新1:

工具:

Qt Creator 3.4.1 (ubuntu 14.04)

Qt 5.4.2 (GCC 4.6.1,64位)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-21 16:23:33

TL;DR:这就是为什么您确实需要发布再现崩溃所需的所有代码。

你的代码有效-没有崩溃。你的问题就这样回答了,即使答案对你和其他人都是完全无用的。不要问那些只能以一种无法帮助你的方式回答的问题。

除了在现代C++中没有位置的可怕的C类之外,在您的代码中唯一突出的地方是在main开始执行之前就创建了HRAD实例。取决于HRAD的构造函数在做什么,这可能是一件坏事。

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

旧码

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

你应该在你的问题中提供所有这些--有足够的“其他东西”让你崩溃。假设它崩溃或以其他方式重现了你的问题,下面的将被视为斯考斯,并使你的问题对社区有价值。

代码语言:javascript
运行
复制
#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 ):

代码语言:javascript
运行
复制
#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的实现。

代码语言:javascript
运行
复制
void HRAD::registerDevice(REGISTER_DEVICE_PARAMS_t* params) {
   params->cbFn("some ibd");
}

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

代码语言:javascript
运行
复制
Starting bad-c-aargh-31542746...
HRAD_CONTROLLER: Device Registered: ibd =  "some ibd"
bad-c-aargh-31542746 exited with code 0

返工

您似乎使用回调和通过指针传递值,就像在C中一样。我们将消除C++中不必要的C类型,我们将利用C++11的特性使回调更加可用。

如前所述,下面的代码仅仅是与评注交织在一起。您可以将其复制粘贴到main.cpp中,删除注释,编译并运行。它已经完成了。

首先,让我们包括functional头以引入std::function,我们将去掉C风格的宏:

代码语言:javascript
运行
复制
#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方法的结构,并从这些方法获得响应:

代码语言:javascript
运行
复制
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引用传递。可选回调可以兼容lambda、函式实例、函数指针等。缺省构造的值使它们成为可选的。您可以将它们排除在调用之外,编译器将使用默认值。currentPublicStationID,大概是一个全局变量,也属于HRAD

代码语言:javascript
运行
复制
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宏定义的。它将被实例化,线程-安全,在第一次使用。它充当一个指针-要获取全局实例,应该使用->操作符。

代码语言:javascript
运行
复制
Q_GLOBAL_STATIC(HRAD, hbr) // no semicolon needed

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

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
int main()
{
   registerDevice();
   return 0;
}

此代码可以工作,并产生以下输出:

代码语言:javascript
运行
复制
Starting bad-c-aargh-31542746...
"HRAD_CONTROLLER:" Device Registered: ibd =  "some ibd"
got station model
bad-c-aargh-31542746 exited with code 0

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31542746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档