strcpy()上的特权指令运行时错误

时间:2013-09-09 17:28:12

标签: c++ c++builder

我在将C ++ Builder 6项目升级到C ++ Builder XE3时遇到问题。目前我的问题是:当在Release模式下编译并运行时,项目会抛出“Privileged instruction”。我跟踪到strcpy()调用的两个不同for循环的错误。我试图将其更改为strncpy()并包括字符串大小,但无济于事。我所知道的是,当我注释掉这两行时,错误消失了。

相关代码:

/** 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 */
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));
    ReadCalibrationFromUnit(calibr);
}    

void __fastcall TForm1::ReadCalibrationFromUnit(CALIBRATION *reg) {

    // for (int j=0, j < 8, j++) { // Incorrect; but no bearing on actual soln.

    for (int j=0; j < 8; j++) {
        // Here's the problematic line. Another loop exists which does the same
        //   thing for another 18 array members in reg, but is essentially 
        //   identical to this one.
        strcpy(reg[j].name, ADC_names[j]); 
    }
}

我已经尝试了很多东西,例如将ADC_names设为const char,省略对它的extern delcaration,尝试将strncpy()放入reg []数组......

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

真正奇怪的是,当我在发布模式下编译和运行时,此错误才会显示出来。 Debug根本不会出现此错误。

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

我已经尝试过围绕这个问题,但是由于我对内存处理的了解有限,一切看起来都不错。有什么可能导致这种情况的想法吗?

感谢。 -Daniel

2 个答案:

答案 0 :(得分:1)

也许它只是一个副本&amp;在这里发布代码时粘贴错误,但是你是否意识到你的for循环是“错误的”?

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

应该是

for (int j=0; j < 8; j++)
对吗?想知道,为什么你不会得到编译器错误,但我不熟悉C ++ builder的编译器......

答案 1 :(得分:0)

通过研究@UlrichEckhardt的评论来解决这个问题:

  

也许它是经典的“静态初始化命令惨败”的一种形式?

事实证明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]);
    }
}