c++runtimeunhandled-exceptionfirst-chance-exception

Unhandled Exceptions in simple application


I'm fairly new to C++ and coding in general, and I'm using Visual Studio 2013 Desktop to write a simple program to collect and perform some operations on data from a .CSV file. The program seems to compile and run fine, and asks me to type in a name for the file to be opened. Just like I intended, if I type an invalid file name, the program will display an error message and terminate, however if I enter the correct name I get a message that says

"Unhandled exception at 0x0F16A9E8 (msvcr120d.dll) in TestIO.exe: 0xC0000005: Access violation reading location 0xCCCCCCC0."

With the options to Break or Continue. If I press Continue, it displays the same message again, and goes on infinitely until I press "Break" and stop the debugging. I have absolutely no idea what's going on here, can anyone shed some light on this? It would be much appreciated.

Edit: Here is my main(). Hope this helps more, sorry for not including it before.

int main()
{
    int numDays = 0, streams;
    string* date;
    string line, filename;
    DailyData* days;
    cout << "Enter file name: ";
    getline(cin, filename);
    ifstream infile;
    infile.open(filename); 
    if (infile.fail())
    {
        cout << "Error opening input file" << endl;
        return 0;
    }
    while (getline(infile, line))
        numDays++;
    date = new string[numDays];
    for (int i = 0; i < numDays; i++)
        getline(infile, date[i]);
    days = new DailyData[numDays];
    for (int i = 0; i < numDays; i++)
    {
        getData(date[i], streams);
        days[i] = DailyData(date[i], streams);
    }
    cout << "Max Streams: " << maxStreams(days, numDays) << endl;
    cout << "Min Streams: " << minStreams(days, numDays) << endl;
    cout << "Avg Streams: " << average(days, numDays) << endl;
    cout << "Tot Streams: " << total(days, numDays) << endl;
    delete[] days;
    delete[] date;
    infile.close();
    return 0;
}

Edit 2: Here is some of the stuff you guys asked for

void getData(string& d, int& s)
{
    int start = 0, end = 0, i = 0;
    string p[14];
    while (start != string::npos)
    {
        end = d.find(",", start); 
        p[i] = d.substr(start, end - start);
        start = end + 1;
        i++;
    }
    d = p[0];
    s = atoi(p[5].c_str());
}

And here is DailyData with it's constructors

class DailyData
{
    public:
    DailyData() :date("NULL"), streams(0){}
    DailyData(string d, int s) :date(d), streams(s){}
    string getDate(){ return date; }
    int getStreams(){ return streams; }
    friend ostream& operator << (ostream&, DailyData&);
    private:
        string date;
        int streams;
};

Edit 3: I changed my code to use vectors instead of arrays. Along with changing int main(), I made sure to change the arguments in all the function definitions/declarations. I'm still getting the same Unhandled Exception error I originally got. Here's the new code snippet:

vector<string> date;
vector<DailyData> days;

//...

while (getline(infile, line))
{
    date.push_back(line);
    getData(date.back(), streams);
    days.push_back(DailyData(date.back(), streams));
}
numDays = days.size();

Solution

  • It appears your code is calling getline on the inputfile after you've already read to the end of the file

    while (getline(infile, line))
        numDays++;
    
    // above reads every line in the file,
    // then you call this, even though while(getline) has returned false:
    
    for (int i = 0; i < numDays; i++)
        getline(infile, date[i]);
    

    If you're new to programming always use curly braces to show the body of a loop so you can see where the loop block execution begins and ends.

    Also, in practice, its best to learn to use a debugger. It will be the most valuable thing you ever do as a programmer.

    Edit:

    here's how you could use a dynamically resizable vector instead of a fixed size array:

    std::vector<string> dates;
    
    //...
    
    while( getline(infile, line) )
    {
        dates.push_back(line);
    }
    

    If you need more info, search for C++ vector.

    Edit2:

    Now that the code to getData has been posted I think the problem is in there. For a start this code:

    while (start != string::npos)
    {
        end = d.find(",", start); 
        p[i] = d.substr(start, end - start);
        start = end + 1;
        i++;
    }
    

    looks very dangerous.

    p[i] = d.substr(start, end - start); 
    

    will result in weird behaviour if end == string::npos which will occur whenever d.find does not find a comma.

    similarly start = end + 1 will not do what you expect if end == string::npos

    further p[i] = ... will only work for values of i less than 13. I see no checks to guarantee this.

    My first suggestion would be to check if end == string::npos and only perform other the operations if it isn't.

    Hope that helps, the behaviour of this code depends heavily on what your input data looks like, which is why its best to use a debugger.