2013-09-09 3 views
0

У меня возникла проблема с обновлением проекта C++ Builder 6 до C++ Builder XE3. В настоящее время моя проблема заключается в следующем: при компиляции и запуске в режиме выпуска проект генерирует «Привилегированную инструкцию». которую я отслеживал до двух разных циклов, связанных с вызовами strcpy(). Я попытался изменить это на strncpy() и включить размер символьной строки, но безрезультатно. Все, что я знаю, это то, что когда я прокомментирую эти две строки, ошибка уходит.Привилегированная ошибка выполнения команды на strcpy()

код Соответствующая:

/** 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 константный символ, опуская Экстерн delcaration на него, пытаясь в strncpy() в регистр [] массив ...

Из того, что я могу сказать, вся память была должным образом распределена для учета всего, ADC_names[] далека от нуля, как мы ее определяем до ev en, входящий в конструктор формы. Пробовал редактирование calibr[] непосредственно в цикле for, а не в переменной функции reg, в которую она передается, и все же ошибка все еще существует.

Что действительно странно в том, что эта ошибка появляется только при компиляции и запуске в режиме Release. Debug не дает этой ошибки вообще.

Также ошибка изменяется по мере выполнения программы. «Привилегированная ошибка» отображается только при запуске, когда функция вызывается нажатием кнопки автосоединения. Позже, когда кнопка будет нажата вручную, ошибка изменится на «Нарушение доступа по адресу 00000000. Чтение адреса 00000000».

Я пробовал обворачивать голову вокруг этого, но все, кажется, выглядит хорошо с моим ограниченным знанием управления памятью. Любая идея о том, что может быть причиной этого?

Спасибо. -Daniel

+0

Поскольку вы обновляете/портирования, почему бы не просто идти в 'станд :: string'? – Brian

+0

Как называется 'ReadCalibrationFromUnit'? Что такое 'reg', когда он вызывается? –

+0

Я подумал о том, чтобы обновить каждый экземпляр до чего-то вроде UnicodeString, но, похоже, я помню, что я сталкивался с большими ошибками символов, когда я пытался это сделать раньше в другом проекте. Я предполагаю, что рассуждаю, я понятия не имею, где все эти значения фактически используются, и как далеко мне придется идти, чтобы обновить все, поскольку я только частично прохожу через код, чтобы просто очистить его форматирование. FPGA, к которому это соединение подключается, только принимает стандартные символы, а не Юникод или широкие символы или что-то еще, поэтому я не уверен, что это поле «имя регистра» когда-либо отправляется в устройство вообще. Но я буду помнить об этом! – depwl9992

ответ

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]); 
    } 
} 
1

Возможно, это всего лишь копия & Ошибка при вставке при размещении кода здесь, но вы поняли, что ваш for-loop является «неправильным»?

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

должен быть

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

правильно? Удивление, почему вы не получите ошибку компиляции, но я не знаком с компилятором строителя C++ ...

+0

Ох. Ха. Да ... Я напечатал его здесь неправильно. Это наверняка привлекло бы это, если бы оно было в самом коде. – depwl9992