从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(¶ms);
}
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之前的值。故障:
如果您在调试时发现“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;
价值观变得像这样:
现在“版本”也“无法访问”。
知道为什么会这样吗?
感谢。
更新1:
工具:
Qt Creator 3.4.1(ubuntu 14.04)
Qt 5.4.2(GCC 4.6.1,64 bit)
答案 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(¶ms);
}
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
getStationModel
和registerDevice
函数将使用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
请注意,没有任何手动内存管理。原始指针既不作为参数也不作为成员使用。