Место чтения нарушения доступа с использованием открытого потока файлов

#c #exception

#c #исключение

Вопрос:

Я знаю, что этот вопрос задавался много раз. Но в моем случае ошибка присутствует не всегда, поэтому я думаю, что это может быть по-другому. Я использую C , Visual Studio 2013, Windows 7 x64.

Вот соответствующий код:

 void writeDATAToFile(const char *fname, string title, const VecDoubamp; spec_x, const VecDoubamp; spec_y, const VecDoubamp; freq)
{
    ofstream of;
    of.open(fname, ios_base::out);
    if (!of.is_open())
    {
        return;
    }
    of << "somename" << endl;
    of << "WAVES/S" << "t" << title << endl;
    of << "BEGIN" << endl;
    for (int i=0; i<spec_x.size(); i  )
    {
        of << spec_x[i] << "ttt" << spec_y[i] << "ttt" << freq[i]<<endl;
    }
    of << "END" << endl;
    of.close();
}
 

Предполагается, что эта функция записывает данные спектра (вычисленные ранее в программе) и записывает их в файл. Некоторые данные спектра не вызовут проблем, некоторые будут. Ошибка находится в цикле for.
Вот окно ошибки:введите описание изображения здесь

Комментарии:

1. И вы абсолютно уверены, что два других вектора всегда имеют точно такой же размер, как spec_x.size() ? (И есть только один for цикл, который я могу обнаружить, кстати)

2. Когда вы говорите «Ошибка во втором цикле for», я вижу только один

3. Извините, да, есть только цикл for.

4. @student1: Докажите это утверждением.

5. Может ли нарушение доступа исходить из fname вместо этого? 😉

Ответ №1:

Вы передаете 3 вектора своей функции:

 const VecDoubamp; spec_x, const VecDoubamp; spec_y, const VecDoubamp; freq
 

но вы никогда не проверяете, что они имеют одинаковый размер.

В вашем цикле (не во «втором» цикле, как вы сказали в своем вопросе, в опубликованном вами коде есть только один цикл) вы повторяете итерацию spec_x и используете тот же индекс i для индексации в два других вектора.

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

Комментарии:

1. примечание: Это нарушение доступа, а не исключение V . Я предполагаю, что это может не отображаться в режиме выпуска, например, с непроверенными итераторами….

2. Все они имеют одинаковую длину, но я перепроверю.

3. @doctorlove я не понимаю, что вы имеете в виду?

4. Когда я сказал V, я имел в виду C … опечатка. Это не исключение C , которое вы можете перехватить

5. @student1: вы можете прочитать о проверенных итераторах в msdn: msdn.microsoft.com/en-us/library/aa985965.aspx . Обратите внимание: Если _SECURE_SCL определено как 1, небезопасное использование итераторов вызывает ошибку времени выполнения, и программа завершается. Если определено как 0, проверенные итераторы отключены. По умолчанию значение _SECURE_SCL равно 0 для сборок выпуска и 1 для сборок отладки. Таким образом, по умолчанию итераторы проверяются для сборок отладки и не проверяются для сборок выпуска.

Ответ №2:

В сообщении об ошибке ясно говорится, что он пытается прочитать то, чего не должно быть.

Вы кодируете циклы таким образом:

  for (int i=0; i<spec_x.size(); i  )
 {
        of << spec_x[i] << "ttt" << spec_y[i] << "ttt" << freq[i]<<endl;
 }
 

Это предполагает spec_x , spec_y и freq имеют одинаковый размер.

  • Вы можете проверить это перед циклом и выдать ошибку, если это предварительное условие не выполняется.
  • Вы могли бы зациклиться на самом маленьком размере из всех трех.
  • Вы могли бы оставить эту функцию как есть и поставить проверки там, где вы изначально заполняли данные.

Примечание — отладчик пытается вам помочь. Если вы нажмете «break», это вызовет у вас стек вызовов, и тогда вы сможете точно увидеть, какая переменная вызывает проблему.

Комментарии:

1. Спасибо, я еще раз проверю проблему с длиной и вернусь.