STATUS_ACCESS_VIOLATION при чтении файла int struct - PullRequest
2 голосов
/ 24 февраля 2012

Я читаю 3 вещи в структуре Песни: название песни, исполнитель, размер файла. Я получаю сообщение об ошибке при запуске программы, хотя она выглядит правильно.

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;

struct Songs
{
    string title;
    string artist;
    int size;
};

int main ()
{
    int num_songs;

    Songs song[num_songs];

    ifstream fin;
    fin.open("songlist.txt")

    while (fin.good()) {
        fin >> song[num_songs].title;
        fin >> song[num_songs].artist;
        fin >> song[num_songs].size;
        num_songs++;
    }
    fin.close();

    cout << "welcome to the show" << endl;
    return 0;
}

Почему программа выдает STATUS_ACCESS_VIOLATION при чтении файла в struct?

Ответы [ 4 ]

4 голосов
/ 24 февраля 2012

Ваша программа не «выглядит правильно», в ней есть ряд ошибок, подробно описанных в других ответах.

Вот программа, которая правильно читает в списке песен. Обратите внимание, что это четыре альтернативных метода для чтения файла. Выберите тот, который наиболее вам подходит, и удалите остальные три.

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <iterator>
#include <algorithm>

struct Song
{
    std::string title;
    std::string artist;
    int size;
    Song() : size() { }
    Song(const Song& song) :
      title(song.title), artist(song.artist), size(song.size) { }
    Song(std::string title, std::string artist, int size) :
      title(title), artist(artist), size(size) { }
};

std::istream&
operator>>(std::istream& is, Song& song) {
    return is >> song.title >> song.artist >> song.size;
}

int main ()
{    
   std::vector< Song > songs;

   std::ifstream fin;
   fin.open("songlist.txt");

   // You could read the songs this way:
   std::copy(std::istream_iterator<Song>(fin),
       std::istream_iterator<Song>(),
       std::back_inserter(songs));

   // Or, if you don't like std::copy, you can do this:
   Song song;
   while(fin >> song)
       songs.push_back(song);

   // Or, if you don't like operator>>(istream, Song), you can do this:
   std::string artist;
   std::string title;
   int size;
   while(fin >> artist >> title >> size)
       songs.push_back(Song(artist, title, size));

   // Or, if you don't like using the constructor:
   while(fin >> artist >> title >> size) {
       Song song;
       song.artist = artist;
       song.title = title;
       song.size = size;
       songs.push_back(song);
    }


    int num_songs = songs.size();
    std::cout << "welcome to the show: " << num_songs << "\n";
    return 0;
}
1 голос
/ 24 февраля 2012

Songs song[num_songs]; где инициализация num_songs?

1 голос
/ 24 февраля 2012

Ну, ваш код довольно сумасшедший ... насколько велик массив "song"?На данный момент вы инициализируете его до «неопределенного» размера.Вы ДОЛЖНЫ инициализировать num_songs.Неспособность сделать это означает, что он «может» использовать любое значение.Вы получаете нарушение прав доступа, потому что инициализируете массив до размера num_songs (мы возьмем произвольное число 70 в качестве примера, хотя оно может быть буквально любым числом), а затем вы начинаете запись в массив с тем же значением (который находится за концом массива).Это нарушение прав доступа, потому что вы впоследствии столкнетесь с памятью, которой не владеет ваш процесс.Следовательно, вы нарушаете пространство памяти, пытаясь использовать память, к которой у вас нет доступа .

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

Было бы намного лучше использовать вектор stl следующим образом:

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>

using namespace std;

struct Songs
{
    string title;
    string artist;
    int size;

    Songs() {};
};

int main ()
{    
   std::vector< Songs > song;

   ifstream fin;
   fin.open("songlist.txt")

   while (fin.good()) 
   {
       song.push_back( Songs() );
       fin >> song.back().title;
       fin >> song.back().artist;
       fin >> song.back().size;
   }
   fin.close();

   int num_songs = song.size();

   cout << "welcome to the show" << endl;
   return 0;
}
0 голосов
/ 24 февраля 2012

У вас есть это:

int num_songs;

Songs song[num_songs];

Это не разрешено C ++. Размер массива должен быть постоянным выражением во время компиляции.

Компилятор GNU имеет расширение, которое позволяет это, но даже в GNU значение переменной, используемой для определения размера массива, должно иметь определенное значение.

Когда вы пишете в массив с неопределенным размером, вы в конечном итоге достигаете точки памяти, где вам не разрешено писать, или вы перезаписываете некоторую память и меняете значение чего-то другого в вашей программе. Нарушение доступа - абсолютно законный ответ на эту ситуацию.

Вместо этого вы должны использовать контейнер C ++, такой как вектор, список или deque. Они могут динамически расти, чтобы вместить любое количество элементов в вашем файле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...