我在将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
答案 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]);
}
}