析构函数后出现分段错误

发布于 2024-08-27 01:05:55 字数 3933 浏览 9 评论 0原文

我正在制作一个小文件读取和数据验证程序,作为我的 TAFE(高等教育学院)课程的一部分,其中包括检查和验证日期。

我决定最好用一个单独的类来完成,而不是将其集成到我的主驱动程序类中。

问题是我的测试程序运行后出现分段错误(核心转储)。据我所知,错误发生在程序终止时,在调用析构函数后弹出。到目前为止,我还没有找到这个错误的原因,并希望一些开明的灵魂可以告诉我我的方式的错误。

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);

}

最后,

#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";

}

我在测试程序中留下了一些无关的 cout 语句,我一直用这些语句来尝试查找错误。

我先谢谢你了。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

雅心素梦 2024-09-03 01:05:55

更改:

private:
    int days[];

至:

private:
    int days[12];

Change:

private:
    int days[];

to:

private:
    int days[12];
童话 2024-09-03 01:05:55

问题是您从未真正初始化 date 类型中的 days 字段。这意味着当您在构造函数中设置值时,您正在访问未初始化的内存。

您需要以某种方式显式初始化 days 值。最简单的解决方法是使用向量作为类型或将数组的大小硬编码为 12。

private:
  int days[12];

或者

private:
  std:vector<int> days;

...
date::date() {
  days.push_back(31);
  days.push_back(28);
  ...
}

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);
  ...
}
久光 2024-09-03 01:05:55

你没有说你正在使用哪个编译器,但如果我使用带有 -Wall-pedantic 标志的 g++ 编译此代码:

struct S {
    int a[];
};

int main() {
    S s;
}

消息:

warning: ISO C++ forbids zero-size array 'a'

我收到警告 是您应该始终使用尽可能多的编译器警告进行编译 - 它可以节省您大量的时间并产生更正确的代码。

You don't say which compiler you are using, but if I compile this code using g++ with the -Wall and -pedantic flags:

struct S {
    int a[];
};

int main() {
    S s;
}

I get the warning message:

warning: ISO C++ forbids zero-size array 'a'

The moral is that you should always compile using as many compiler warnings as possible - it can save you mountains of time and result in more correct code.

榕城若虚 2024-09-03 01:05:55

我同意这个问题的先前答案,但我会添加其正确性的基本原理:

每当您尝试访问不允许访问的内存时,就会导致分段错误。

http://en.wikipedia.org/wiki/Segmentation_fault

您无权访问 " days[0]”到 days“[11]”,因为计算机没有给出“days[]”变量,您声明了足够的内存来容纳任何元素,因此当您尝试访问所述元素时,它会引发段错误。

任何未使用“new”运算符声明的变量都将放置在“堆栈”上,“堆栈”是计算机划分出来供程序使用的连续内存块。为了保持堆栈中存储的所有内容都是连续的,计算机只会在您请求时仅提供您需要使用的内存量,因此,例如,如果您请求创建一个 int,它只会为您提供足够的内存存储单个 int 的内存。

当你写下 int days[]; 行时计算机尝试评估它需要多少内存,将其评估为空数组,并为您提供足够的内存来存储所述空数组。由于计算机没有为您的数组提供超出空数组所需的任何额外空间,因此它知道您尝试访问该数组中的内存尚未分配给它,因此它会引发分段错误并崩溃。

如果您还没有在计算机科学课上了解“堆栈”和“堆”,那么抱歉,如果这有点让人不知所措,但我可能把事情复杂化了,我想您可能很快就会了解。

I agree with the previous answers to this question, but I would add the rationale for their correctness:

Segmentation faults are caused whenever you attempt to access memory you are not allowed to access.

http://en.wikipedia.org/wiki/Segmentation_fault

You were not allowed to access "days[0]" through days "[11]" because the computer had not given the "days[]" variable that you declared enough memory to hold any elements, thus when you tried to access said elements, it threw a segfault.

Any variables not declared with the "new" operator are placed on the "stack," which is a contiguous chunk of memory the computer has sectioned away for use by the program. In order to keep everything stored in the stack contiguous, the computer will only give exactly the amount memory you require for you to use whenever you request it, so that if you request to create an int, for example, it will only give you enough memory to store that single int.

When you wrote the line int days[]; the computer attempted to evaluate how much memory it would require, assessed it as an empty array, and gave you enough memory to store said empty array. Because the computer did not give your array any extra space beyond what was needed for an empty array, it knew that the memory you tried to access in that array had not been assigned to it, so it threw a segmentation fault and crashed.

If you have not yet learned about the "stack" and "heap" in your computer science class, then sorry if this is a bit overwhelming, but I perhaps overcomplicated things, and I think you likely soon will.

零度℉ 2024-09-03 01:05:55
int days[];

这是一个非标准扩展。您必须指定数组的大小,例如:

static const MonthCount = 12;
int days[MonthCount];

要实际有一个数组可供使用。否则你有一个“零大小的数组”(不是标准的!)。每次使用当前数组的任何元素时,程序都会占用内存。

int days[];

This is a non-standard extension. You must specify a size for the array, such as:

static const MonthCount = 12;
int days[MonthCount];

To actually have an array to use. Otherwise you have a "zero-sized array" (not standard!). Your program is tromping over memory every time you use any element of your current array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文