Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting segmentation fault after destructor

I'm making a small file reading and data validation program as part of my TAFE (a tertiary college) course, This includes checking and validating dates.

I decided that it would be best done with a seperate class, rather than integrating it into my main driver class.

The problem is that I'm getting a segmentation fault(core dumped) after my test program runs. Near as I can tell, the error occurs when the program terminates, popping up after the destructor is called. So far I have had no luck finding the cause of this fault, and was hoping that some enlightened soul might show me the error of my ways.

date.h

#ifndef DATE_H
#define DATE_H

#include <string>
using std::string;

#include <sstream>
using std::stringstream;

#include <cstdlib>
using std::exit;

#include <iostream>
using std::cout;
using std::endl;

class date {

    public:
        explicit date();
        ~date();
        bool before(string dateIn1, string dateIn2);
        int yearsBetween(string dateIn1, string dateIn2);
        bool isValid(string dateIn);
        bool getDate(int date[], string dateIn);
        bool isLeapYear(int year);
    private:
        int days[];

};
#endif

date.cpp

#include "date.h"

date::date() {

    days[0] = 31;
    days[1] = 28;
    days[2] = 31;
    days[3] = 30;
    days[4] = 31;
    days[5] = 30;
    days[6] = 31;
    days[7] = 31;
    days[8] = 30;
    days[9] = 31;
    days[10] = 30;
    days[11] = 31;

}

bool date::before(string dateIn1, string dateIn2) {

    int date1[3];
    int date2[3];

    getDate(date1, dateIn1);
    getDate(date2, dateIn2);

    if (date1[2] < date2[2]) {

        return true;

    } else if (date1[1] < date2[1]) {

        return true;

    } else if (date1[0] < date2[0]) {

        return true;

    }

    return false;

}

date::~date() {

    cout << "this is for testing only, plox delete\n";

}

int date::yearsBetween(string dateIn1, string dateIn2) {

    int date1[3];
    int date2[3];

    getDate(date1, dateIn1);
    getDate(date2, dateIn2);

    int years = date2[2] - date1[2];

    if (date1[1] > date2[1]) {

        years--;

    } 

    if ((date1[1] == date2[1]) && (date1[0] > date2[1])) {

        years--;

    }

    return years;

}

bool date::isValid(string dateIn) {

    int date[3];

    if (getDate(date, dateIn)) {

        if (date[1] <= 12) {

            int extraDay = 0;

            if (isLeapYear(date[2])) {

                extraDay++;

            }

            if ((date[0] + extraDay) <= days[date[1] - 1]) {

                return true;

            }

        }

    } else {

        return false;

    }

}

bool date::getDate(int date[], string dateIn) {

    string part1, part2, part3;

    size_t whereIs, lastFound;

    whereIs = dateIn.find("/");

    part1 = dateIn.substr(0, whereIs);

    lastFound = whereIs + 1;

    whereIs = dateIn.find("/", lastFound);

    part2 = dateIn.substr(lastFound, whereIs - lastFound);

    lastFound = whereIs + 1;

    part3 = dateIn.substr(lastFound, 4);

    stringstream p1(part1);
    stringstream p2(part2);
    stringstream p3(part3);

    if (p1 >> date[0]) {

        if (p2>>date[1]) {

            return (p3>>date[2]);

        } else {

            return false;

        }

        return false;

    }

}

bool date::isLeapYear(int year) {

    return ((year % 4) == 0);

}

and Finally, the test program

#include <iostream>
using std::cout;
using std::endl;

#include "date.h"

int main() {

    date d;

    cout << "1/1/1988 before 3/5/1990 [" << d.before("1/1/1988", "3/5/1990")
        << "]\n1/1/1988 before 1/1/1970 [" << d.before("a/a/1988", "1/1/1970")
        <<"]\n";

    cout << "years between 1/1/1988 and 1/1/1998 [" 
        << d.yearsBetween("1/1/1988", "1/1/1998") << "]\n";

    cout << "is 1/1/1988 valid [" << d.isValid("1/1/1988") << "]\n" 
        << "is 2/13/1988 valid [" << d.isValid("2/13/1988") << "]\n"
        << "is 32/12/1988 valid [" << d.isValid("32/12/1988") << "]\n";

    cout << "blerg\n";

}

I've left in some extraneous cout statements, which I've been using to try and locate the error.

I thank you in advance.

like image 872
user303491 Avatar asked Mar 28 '10 08:03

user303491


People also ask

Why do I keep getting segmentation fault?

In practice, segfaults are almost always due to trying to read or write a non-existent array element, not properly defining a pointer before using it, or (in C programs) accidentally using a variable's value as an address (see the scanf example below).

How is segmentation fault generated?

A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).

Why does segmentation fault occur in C++?

A segmentation fault occurs when your program attempts to access an area of memory that it is not allowed to access. In other words, when your program tries to access memory that is beyond the limits that the operating system allocated for your program.

What causes segmentation fault 11 in C++?

1) Segmentation Fault (also known as SIGSEGV and is usually signal 11) occur when the program tries to write/read outside the memory allocated for it or when writing memory which can only be read.In other words when the program tries to access the memory to which it doesn't have access to.


2 Answers

Change:

private:
    int days[];

to:

private:
    int days[12];
like image 184
Paul R Avatar answered Sep 20 '22 03:09

Paul R


The problem is that you never actually initialize the days field in the type date. This means that when you are setting the values in the constructor you are accessing uninitialized memory.

You need to explicitly initialize the days value in some way. The easiest fix is to use a vector for the type or to hard code the size of the array to 12.

private:
  int days[12];

Or

private:
  std:vector<int> days;

...
date::date() {
  days.push_back(31);
  days.push_back(28);
  ...
}
like image 26
JaredPar Avatar answered Sep 22 '22 03:09

JaredPar