strcpy()上的特权指令运行时错误 我有一个问题,将C++ Builder 6项目升级到C++ Builder XE3。目前我的问题是:当在发布模式下编译和运行时,项目抛出“特权指令”。我已经跟踪到围绕strcpy()调用的两个不同for循环的错误。我尝试将其更改为strncpy(),并包含字符串大小,但没有效果。我所知道的是,当我注释掉这两行时,错误就消失了

strcpy()上的特权指令运行时错误 我有一个问题,将C++ Builder 6项目升级到C++ Builder XE3。目前我的问题是:当在发布模式下编译和运行时,项目抛出“特权指令”。我已经跟踪到围绕strcpy()调用的两个不同for循环的错误。我尝试将其更改为strncpy(),并包含字符串大小,但没有效果。我所知道的是,当我注释掉这两行时,错误就消失了,c++,c++builder,C++,C++builder,相关代码: /** Main.h */ class TForm1 : public TForm { published: void __fastcall ReadCalFromUnitBtnClick(TObject *Sender); private: struct CALIBRATION { char name[64]; float gain1; float gain2;

相关代码:

/** Main.h */
class TForm1 : public TForm {
    published:
        void __fastcall ReadCalFromUnitBtnClick(TObject *Sender);
    private:
        struct CALIBRATION {
            char name[64];
            float gain1;
            float gain2;
            float offset;
            ...
            ... // A few more values that aren't pertinent to this question.
        };
        CALIBRATION calibr[256];
        void __fastcall TForm1::ReadCalibrationFromUnit(CALIBRATION *reg);
};
extern char *ADC_names[];

/**Main.cpp*/
字符*ADC_名称[]={
“字符串1”,
“字符串2”,
“字符串3”,
“字符串4”,
“字符串5”,
“字符串6”,
“字符串7”,
“字符串8”
};
void _fastcall TForm1::ReadCalFromUnitBtnClick(TObject*Sender){
memset(calibr,0,sizeof(calibr));
从单元(calibr)读取校准值;
}    
void\uuu fastcall TForm1::ReadCalibrationFromUnit(CALIBRATION*reg){
//对于(intj=0,j<8,j++){//不正确;但与实际解无关。
对于(int j=0;j<8;j++){
//这是有问题的一行。另一个循环也有同样的作用
//对于reg中的另外18个数组成员来说,这是一件很重要的事情,但本质上是
//和这个一模一样。
strcpy(reg[j].名称,ADC_名称[j]);
}
}
我已经尝试了很多方法,比如将ADC_名称设置为const char,省略其上的外部增量,尝试将strncpy()插入reg[]数组

据我所知,所有的内存都已正确分配到所有内容,
ADC\u names[]
远远不是空的,因为我们甚至在进入表单构造函数之前就定义了它。尝试编辑
calibr[]
直接在for循环中,而不是它被传递到的
reg
函数变量中,但错误仍然存在

真正奇怪的是,这个错误只在我以发布模式编译和运行时出现。调试根本没有给出这个错误

此外,错误会随着程序执行的进行而变化。“特权错误”仅在启动时通过自动连接按钮单击调用函数时显示。稍后,手动单击按钮时,错误会变为“地址00000000处的访问冲突。读取地址00000000。”

我试着用头脑来思考这个问题,但由于我对内存处理的知识有限,一切看起来都很好。你知道是什么导致了这个问题吗

谢谢。
-Daniel

当您在此处发布代码时,可能只是复制粘贴错误,但是您是否意识到for循环是“错误的”

for(int j=0,j<8,j++)
应该是

for (int j=0; j < 8; j++)
for(int j=0;j<8;j++)

右?想知道,为什么你不会得到编译器错误,但我不熟悉C++ Builder的编译器…< /P> < P>这是通过研究@ UlrichEckhardt:< /P>的注释而确定的。


也许这是一种典型的“静态初始化命令失败”

结果是
memset(calibr,0,sizeof(calibr))
执行的时间比函数调用
ReadCalibrationFromUnit(calibr);
要长。正式地说,这种“静态初始化顺序的失败”表明,你有50/50的机会让程序正确地执行它。然而,在我的例子中,这个问题每次都会发生

为了修复它,我只需将代码从
ReadCalibrationFromUnit()
函数移回
ReadCalFromUnitBtnClick()
事件,因为此事件是唯一调用第二个函数的事件,使得第二个函数的存在变得多余和不必要

现在我的代码出现了:

/** Main.cpp */
char *ADC_names[] = {
   "String 1",
    "String 2",
    "String 3",
    "String 4",
    "String 5",
    "String 6",
    "String 7",
    "String 8"
};

void __fastcall TForm1::ReadCalFromUnitBtnClick(TObject *Sender) {
    memset(calibr, 0, sizeof(calibr));
    for (int j = 0; j < 8; j++) {
        strcpy(calibr[j].name, ADC_names[j]);
    }
}
/**Main.cpp*/
字符*ADC_名称[]={
“字符串1”,
“字符串2”,
“字符串3”,
“字符串4”,
“字符串5”,
“字符串6”,
“字符串7”,
“字符串8”
};
void _fastcall TForm1::ReadCalFromUnitBtnClick(TObject*Sender){
memset(calibr,0,sizeof(calibr));
对于(int j=0;j<8;j++){
strcpy(calibr[j].名称,ADC_名称[j]);
}
}

既然您正在升级/移植,为什么不直接转到
std::string
?如何调用
ReadCalibrationFromUnit
呢?调用
reg
的确切时间是什么?我曾考虑过将每个实例升级到类似UnicodeString的版本,但我似乎记得在尝试之前遇到了大字符错误或者在另一个项目上。我想我的理由是,我不知道所有这些值实际在哪里使用,以及我要升级到什么程度,因为我只是在代码的一部分来清理它的格式。这连接到的FPGA只接受标准字符,而不是Unicode或宽字符或任何东西,所以我不确定如果此“注册名称”字段始终发送到单元。但我会记住它!如果y程序在发布模式下崩溃,而不是在调试模式下崩溃,那么这通常是您使用未初始化的局部变量的迹象。原因是调试器会将所有数据(包括局部变量)归零,这意味着指针在调试器中时为
NULL
。如果检查
NULL
指针,然后未初始化的局部变量将通过,因为未初始化变量的内容是非NULL的(它们的值未定义,大部分是随机的)。这可能是经典的“静态初始化顺序失败”的一种形式哦。哈。是的……我在这里打错了。如果它是在实际代码中,它肯定会捕捉到。
for (int j=0; j < 8; j++)
/** Main.cpp */
char *ADC_names[] = {
   "String 1",
    "String 2",
    "String 3",
    "String 4",
    "String 5",
    "String 6",
    "String 7",
    "String 8"
};

void __fastcall TForm1::ReadCalFromUnitBtnClick(TObject *Sender) {
    memset(calibr, 0, sizeof(calibr));
    for (int j = 0; j < 8; j++) {
        strcpy(calibr[j].name, ADC_names[j]);
    }
}