程序不会按照构造函数进行顺序进行,从而导致非初始化的变量

Program does not go in order through constructor thus leading to uninitialized variables

本文关键字:变量 初始化 顺序 程序 构造函数      更新时间:2023-10-16

我在尝试使用MSVC 2013 32bit在发布模式下编译程序后发现了这个问题。到目前为止,一切都在调试中运行良好,但是我有错误代码:每次我尝试在发行版中运行它时,都会抛出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()调用的返回值。如果失败,您正在调用unload(),但是您正在余下执行其余的执行,试图删除Null指针。

  • 您能确切地告诉它它在哪里崩溃吗?尝试使用未封闭的流将某些内容输出到每个语句之间的控制台,例如std::cerr

这可能像您的工作目录一样愚蠢,而DLL无法加载。

我相信0xc0000409表示堆栈损坏,这可能是由于不仅仅是非初始化变量而造成的。

由于您注意到您必须手动创建一个DLL标头,因此它可能不完全匹配DLL实际实施的内容。除了参数计数/类型和返回类型之外,还有调用约定。由于您没有指定一个,因此您将获得MSVC默认值的内容。但是,如果将DLL与选择不同的惯例的内容一起编译,那么不匹配将引起问题。

实际上,可能的结果可能是堆栈腐败。我不能确定这是您的问题,但我相信这与您的0xc0000409错误是一致的。

理想情况下,该DLL的提供商将能够提供正确的信息。(或至少,如果您可以找出他们使用的编译器,那么您可以研究其默认电话会议。)

) 在

您在构造函数内部声明变量。构造函数仅用于初始化变量,因此请尝试更改该变量(声明在构造函数中没有目的,尤其是默认的目的)