程序没有按顺序通过构造函数,从而导致未初始化的变量
Program does not go in order through constructor thus leading to uninitialized variables
我在尝试使用 Qt 5.4 使用 MSVC 2013 32 位以发布模式编译我的程序后发现了这个问题。到目前为止,一切都在调试中运行良好,但每次我尝试在发布中 运行 时都会抛出错误代码:0xc0000409。看起来这通常意味着某处有初始化变量,所以我通过我的代码设置断点来查看问题出在哪里。我发现,在我的 类 之一的构造函数中,如果我在每一行上设置一个断点,它会从中间某处开始并跳过我为该对象初始化变量的位置。这是代码:
#ifndef AD5932DDS_H
#define AD5932DDS_H
#include "adicyusbusb4.h"
#include <QObject>
#include "picosignal.h"
#include <QLibrary>
class AD5932DDS : public QObject
{
Q_OBJECT
public:
AD5932DDS(QObject *parent = 0);
~AD5932DDS();
private:
QLibrary *myLib;
unsigned int handle;
VendorRequestFunction Vendor_Request;
DisconnectFunction Disconnect;
SearchFunction Search_For_Boards;
ConnectFunction Connect;
DownloadFWFunction Download_Firmware;
};
#endif // AD5932DDS_H
AD5932DDS::AD5932DDS(QObject *parent) : QObject(parent)
{
int searchErrorCode = 0;
int connectErrorCode = 0;
int downloadErrorCode = 0;
unsigned int num_boards = 0;
handle = 0;
char pcFilePath[] = "C:\Users\Jason\Documents\Development\Qt\CrackDetection\AD593x.hex";
char path = 0;
myLib = new QLibrary;
myLib->setFileName("ADI_CYUSB_USB4.dll");
Search_For_Boards = (SearchFunction) myLib->resolve("Search_For_Boards");
Connect = (ConnectFunction) myLib->resolve("Connect");
Download_Firmware = (DownloadFWFunction) myLib->resolve("Download_Firmware");
Vendor_Request = (VendorRequestFunction) myLib->resolve("Vendor_Request");
Disconnect = (DisconnectFunction) myLib->resolve("Disconnect");
if (!Search_For_Boards || !Connect || !Download_Firmware || !Vendor_Request || !Disconnect)
{
myLib->unload();
}
searchErrorCode = Search_For_Boards(VID, PID, &num_boards, &path);
if (num_boards > 0)
{
connectErrorCode = Connect(VID, PID, path, &handle);
if (connectErrorCode == 0)
{
downloadErrorCode = Download_Firmware(handle, pcFilePath2);
}
}
}
如果我单步执行这些调试版本,它中断的第一行就是上面的行
char pcFilePath[] = "C:\Users\Jason\Documents\Development\Qt\CrackDetection\AD593x.hex";
然后它会回到顶部并继续正常下降,一切正常。
但是,如果我在发布模式下输入
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
在 .pro 文件中允许在调试发布版本时设置断点第一个断点是
handle = 0;
从这里开始,跳过上面的初始化,以便
myLib = new QLibrary;
myLib->setFileName("ADI_CYUSB_USB4.dll");
在继续之前它会同时点击这两个地方。我注意到的一件事是,即使在
Search_For_Boards = (SearchFunction) myLib->resolve("Search_For_Boards");
Connect = (ConnectFunction) myLib->resolve("Connect");
Download_Firmware = (DownloadFWFunction) myLib->resolve("Download_Firmware");
Vendor_Request = (VendorRequestFunction) myLib->resolve("Vendor_Request");
Disconnect = (DisconnectFunction) myLib->resolve("Disconnect");
是 运行,如果我检查它们的名称和值,它们中的每一个都列在值下。所以这让我觉得也许每个问题都源于尝试访问这个 dll。
dll 来自这里 https://ez.analog.com/thread/11089 经过多次试验和错误,我能够弄清楚如何在 dll 不提供静态库或带有原型的头文件时使用它。我所做的是在头文件中创建自己的原型,如下所示:
#ifndef ADICYUSBUSB4_H
#define ADICYUSBUSB4_H
const unsigned int VID = 0x0456;
//const unsigned int PID = 0xB20B; // EVAL-AD5932EBZ
const unsigned int PID = 0xB205; // EVAL-AD5930EBZ
const unsigned char WRITE = 0xDD;
const unsigned char SET_STANDBY_PIN = 0xDC;
const unsigned char CLEAR_STANDBY_PIN = 0xDB;
const unsigned char PULSE_CONTROL_PIN = 0xDA;
const unsigned char SET_CONTROL_PIN = 0xD9;
const unsigned char CLEAR_CONTROL_PIN = 0xD8;
const unsigned char PULSE_INTERRUPT_PIN = 0xD7;
typedef unsigned int (*SearchFunction) (unsigned int, unsigned int, unsigned int *, char *);
typedef int (*ConnectFunction) (unsigned int, unsigned int, char, unsigned int *);
typedef int (*DownloadFWFunction) (unsigned int, char []);
typedef int (*VendorRequestFunction) (unsigned int, unsigned char, unsigned short, unsigned short, unsigned char, unsigned short, unsigned char *[]);
typedef int (*DisconnectFunction) (unsigned int);
#endif // ADICYUSBUSB4_H
此方法在调试模式下效果很好,但有些东西不适合发布。
所以要么是我处理这个 dll 不正确(尽管它在调试模式下工作得很好)要么我的程序由于某些未知原因跳过了一些变量初始化。
在启用优化的情况下编译时不要依赖断点或单步执行。优化器将更改、重新排序或删除语句。不要花太多时间试图分析经过优化编译的程序的流程。
QLibrary
是否在某种程度上失败了?检查 isLoaded()
并记录各种 resolve()
调用的 return 值。你正在调用 unload()
以防失败,但你正在愉快地执行其余部分,试图取消引用空指针。
你能说出它崩溃的确切位置吗?尝试使用无缓冲流在每个语句之间向控制台输出一些内容,例如 std::cerr
.
这可能与您的工作目录不同以及 DLL 加载失败一样愚蠢。
我认为 0xc0000409 表示堆栈损坏,这可能是由多种原因引起的,而不仅仅是未初始化的变量。
由于您注意到您必须手动创建 DLL header,因此它可能与实际实现的 DLL 不完全匹配。除了参数 count/types 和 return 类型之外,还有调用约定。由于您没有指定,您将获得 MSVC 的默认值。但是,如果该 DLL 是使用选择不同约定的内容编译的,那么这种不匹配将导致问题。
事实上,一个可能的结果是堆栈损坏。我不能确定这是你的问题,但我相信它与你的 0xc0000409 错误一致。
理想情况下,该 DLL 的提供者能够提供正确的信息。 (或者至少,如果你能找出他们使用的编译器,那么你就可以研究它的默认调用约定。)
但如果它们不能或不会,那么您可能不得不尝试不同的方法并查看哪些看起来可以正常工作。
您是在构造函数内部声明变量。构造函数仅用于初始化变量,因此请尝试更改它(声明在构造函数中没有任何作用,尤其是默认构造函数)
我在尝试使用 Qt 5.4 使用 MSVC 2013 32 位以发布模式编译我的程序后发现了这个问题。到目前为止,一切都在调试中运行良好,但每次我尝试在发布中 运行 时都会抛出错误代码:0xc0000409。看起来这通常意味着某处有初始化变量,所以我通过我的代码设置断点来查看问题出在哪里。我发现,在我的 类 之一的构造函数中,如果我在每一行上设置一个断点,它会从中间某处开始并跳过我为该对象初始化变量的位置。这是代码:
#ifndef AD5932DDS_H
#define AD5932DDS_H
#include "adicyusbusb4.h"
#include <QObject>
#include "picosignal.h"
#include <QLibrary>
class AD5932DDS : public QObject
{
Q_OBJECT
public:
AD5932DDS(QObject *parent = 0);
~AD5932DDS();
private:
QLibrary *myLib;
unsigned int handle;
VendorRequestFunction Vendor_Request;
DisconnectFunction Disconnect;
SearchFunction Search_For_Boards;
ConnectFunction Connect;
DownloadFWFunction Download_Firmware;
};
#endif // AD5932DDS_H
AD5932DDS::AD5932DDS(QObject *parent) : QObject(parent)
{
int searchErrorCode = 0;
int connectErrorCode = 0;
int downloadErrorCode = 0;
unsigned int num_boards = 0;
handle = 0;
char pcFilePath[] = "C:\Users\Jason\Documents\Development\Qt\CrackDetection\AD593x.hex";
char path = 0;
myLib = new QLibrary;
myLib->setFileName("ADI_CYUSB_USB4.dll");
Search_For_Boards = (SearchFunction) myLib->resolve("Search_For_Boards");
Connect = (ConnectFunction) myLib->resolve("Connect");
Download_Firmware = (DownloadFWFunction) myLib->resolve("Download_Firmware");
Vendor_Request = (VendorRequestFunction) myLib->resolve("Vendor_Request");
Disconnect = (DisconnectFunction) myLib->resolve("Disconnect");
if (!Search_For_Boards || !Connect || !Download_Firmware || !Vendor_Request || !Disconnect)
{
myLib->unload();
}
searchErrorCode = Search_For_Boards(VID, PID, &num_boards, &path);
if (num_boards > 0)
{
connectErrorCode = Connect(VID, PID, path, &handle);
if (connectErrorCode == 0)
{
downloadErrorCode = Download_Firmware(handle, pcFilePath2);
}
}
}
如果我单步执行这些调试版本,它中断的第一行就是上面的行
char pcFilePath[] = "C:\Users\Jason\Documents\Development\Qt\CrackDetection\AD593x.hex";
然后它会回到顶部并继续正常下降,一切正常。
但是,如果我在发布模式下输入
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
在 .pro 文件中允许在调试发布版本时设置断点第一个断点是
handle = 0;
从这里开始,跳过上面的初始化,以便
myLib = new QLibrary;
myLib->setFileName("ADI_CYUSB_USB4.dll");
在继续之前它会同时点击这两个地方。我注意到的一件事是,即使在
Search_For_Boards = (SearchFunction) myLib->resolve("Search_For_Boards");
Connect = (ConnectFunction) myLib->resolve("Connect");
Download_Firmware = (DownloadFWFunction) myLib->resolve("Download_Firmware");
Vendor_Request = (VendorRequestFunction) myLib->resolve("Vendor_Request");
Disconnect = (DisconnectFunction) myLib->resolve("Disconnect");
是 运行,如果我检查它们的名称和值,它们中的每一个都列在值下。所以这让我觉得也许每个问题都源于尝试访问这个 dll。
dll 来自这里 https://ez.analog.com/thread/11089 经过多次试验和错误,我能够弄清楚如何在 dll 不提供静态库或带有原型的头文件时使用它。我所做的是在头文件中创建自己的原型,如下所示:
#ifndef ADICYUSBUSB4_H
#define ADICYUSBUSB4_H
const unsigned int VID = 0x0456;
//const unsigned int PID = 0xB20B; // EVAL-AD5932EBZ
const unsigned int PID = 0xB205; // EVAL-AD5930EBZ
const unsigned char WRITE = 0xDD;
const unsigned char SET_STANDBY_PIN = 0xDC;
const unsigned char CLEAR_STANDBY_PIN = 0xDB;
const unsigned char PULSE_CONTROL_PIN = 0xDA;
const unsigned char SET_CONTROL_PIN = 0xD9;
const unsigned char CLEAR_CONTROL_PIN = 0xD8;
const unsigned char PULSE_INTERRUPT_PIN = 0xD7;
typedef unsigned int (*SearchFunction) (unsigned int, unsigned int, unsigned int *, char *);
typedef int (*ConnectFunction) (unsigned int, unsigned int, char, unsigned int *);
typedef int (*DownloadFWFunction) (unsigned int, char []);
typedef int (*VendorRequestFunction) (unsigned int, unsigned char, unsigned short, unsigned short, unsigned char, unsigned short, unsigned char *[]);
typedef int (*DisconnectFunction) (unsigned int);
#endif // ADICYUSBUSB4_H
此方法在调试模式下效果很好,但有些东西不适合发布。
所以要么是我处理这个 dll 不正确(尽管它在调试模式下工作得很好)要么我的程序由于某些未知原因跳过了一些变量初始化。
在启用优化的情况下编译时不要依赖断点或单步执行。优化器将更改、重新排序或删除语句。不要花太多时间试图分析经过优化编译的程序的流程。
QLibrary
是否在某种程度上失败了?检查isLoaded()
并记录各种resolve()
调用的 return 值。你正在调用unload()
以防失败,但你正在愉快地执行其余部分,试图取消引用空指针。你能说出它崩溃的确切位置吗?尝试使用无缓冲流在每个语句之间向控制台输出一些内容,例如
std::cerr
.
这可能与您的工作目录不同以及 DLL 加载失败一样愚蠢。
我认为 0xc0000409 表示堆栈损坏,这可能是由多种原因引起的,而不仅仅是未初始化的变量。
由于您注意到您必须手动创建 DLL header,因此它可能与实际实现的 DLL 不完全匹配。除了参数 count/types 和 return 类型之外,还有调用约定。由于您没有指定,您将获得 MSVC 的默认值。但是,如果该 DLL 是使用选择不同约定的内容编译的,那么这种不匹配将导致问题。
事实上,一个可能的结果是堆栈损坏。我不能确定这是你的问题,但我相信它与你的 0xc0000409 错误一致。
理想情况下,该 DLL 的提供者能够提供正确的信息。 (或者至少,如果你能找出他们使用的编译器,那么你就可以研究它的默认调用约定。)
但如果它们不能或不会,那么您可能不得不尝试不同的方法并查看哪些看起来可以正常工作。
您是在构造函数内部声明变量。构造函数仅用于初始化变量,因此请尝试更改它(声明在构造函数中没有任何作用,尤其是默认构造函数)