0

I have an exception in this code

Date & Date::operator=(const std::string & str){
    if (str.size() != 10)
       throw std::exception("not a date");


    std::regex r;// exception here
    try { // exception here
        std::regex regEx ("^[0-9]{4}[0-9]{2}[0-9]{2}");
    }
    catch (std::exception &e) {
        e.what();
    }
    std::regex delims("([^.,;-]+)");

    std::smatch match;
    if (std::regex_match(str.cbegin(), str.cend(), match, regEx)) {
        std::stringstream ss;
        std::string tmp(match.str());
        std::copy(std::sregex_token_iterator(tmp.cbegin(), tmp.cend(), delims, -1),
        std::sregex_token_iterator(),
        std::ostream_iterator<std::string>(ss, "\n"));
        ss >> year;
        ss >> month;
        ss >> day;
    }
    return *this;
}

If I put similar code in main function in works normaly. I use Visual studio 2015 Community Edition.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Yevhen
  • 329
  • 2
  • 6
  • What is the exception? – hjpotter92 Nov 07 '15 at 07:28
  • There was an unhandled exception at 0x77383E28 in Test.exe: exception of Microsoft C ++: std :: exception of memory address 0x00C7FAF4 – Yevhen Nov 07 '15 at 07:35
  • Sorry, but that code makes little sense. For example, you declare the `regEx` variable in a scope (try/catch) and then use it in an outer scope, where it is not defined. Please post code that can compile. – Christian.K Nov 07 '15 at 07:50
  • Just comment all code after catch block. I have an exception even at that case. – Yevhen Nov 07 '15 at 07:56

1 Answers1

1

Your exception doesn't happen when building the regex but when you throw your own.

First you are checking that your string is exactly 10 characters long. If you put a string of size 10 in your string everything works as it should:

int main()
{
    std::string str = "20151107AB";
    int year = 0;
    int month = 0;
    int day= 0;

    if (str.size() != 10)
        throw std::exception("not a date");

    std::regex regEx("^[0-9]{4}[0-9]{2}[0-9]{2}");
    std::regex delims("([^.,;-]+)");

    std::smatch match;
    if (std::regex_match(str.cbegin(), str.cend(), match, regEx)) {
        std::stringstream ss;
        std::string tmp(match.str());
        std::copy(std::sregex_token_iterator(tmp.cbegin(), tmp.cend(), delims, -1),
            std::sregex_token_iterator(),
            std::ostream_iterator<std::string>(ss, "\n"));
        ss >> year;
        ss >> month;
        ss >> day;
    }
} 

If you remove the "AB" you'll get the error as described in your question.

int main()
{
    std::string str = "20151107";
    int year = 0;
    int month = 0;
    int day= 0;

    if (str.size() != 10)
        throw std::exception("not a date");

    std::regex regEx("^[0-9]{4}[0-9]{2}[0-9]{2}");
    std::regex delims("([^.,;-]+)");

    std::smatch match;
    if (std::regex_match(str.cbegin(), str.cend(), match, regEx)) {
        std::stringstream ss;
        std::string tmp(match.str());
        std::copy(std::sregex_token_iterator(tmp.cbegin(), tmp.cend(), delims, -1),
            std::sregex_token_iterator(),
            std::ostream_iterator<std::string>(ss, "\n"));
        ss >> year;
        ss >> month;
        ss >> day;
    }
}

If you now remove the length-check everything is working as it should again.

int main()
{
    std::string str = "20151107";
    int year = 0;
    int month = 0;
    int day= 0;

    std::regex regEx("^[0-9]{4}[0-9]{2}[0-9]{2}");
    std::regex delims("([^.,;-]+)");

    std::smatch match;
    if (std::regex_match(str.cbegin(), str.cend(), match, regEx)) {
        std::stringstream ss;
        std::string tmp(match.str());
        std::copy(std::sregex_token_iterator(tmp.cbegin(), tmp.cend(), delims, -1),
            std::sregex_token_iterator(),
            std::ostream_iterator<std::string>(ss, "\n"));
        ss >> year;
        ss >> month;
        ss >> day;
    }
}

Also, if you catch the exception everything is still fine (yet the code isn't executed)

int main()
{
    try
    {
        std::string str = "20151107";
        int year = 0;
        int month = 0;
        int day = 0;

        if (str.size() != 10)
            throw std::exception("not a date");

        std::regex regEx("^[0-9]{4}[0-9]{2}[0-9]{2}");
        std::regex delims("([^.,;-]+)");

        std::smatch match;
        if (std::regex_match(str.cbegin(), str.cend(), match, regEx)) {
            std::stringstream ss;
            std::string tmp(match.str());
            std::copy(std::sregex_token_iterator(tmp.cbegin(), tmp.cend(), delims, -1),
                std::sregex_token_iterator(),
                std::ostream_iterator<std::string>(ss, "\n"));
            ss >> year;
            ss >> month;
            ss >> day;
        }
    }
    catch (std::exception& e)
    {
        //handle
    }
}

So my assumption on this is that you don't catch the exception anywhere, which might cause memory corruption as the standard doesn't define whether that stack must be unwound in this case.

I would recommend to 1. read Does it make sense to catch exceptions in the main(...)? 2. correctly catch the exception thrown by Date::operator=

Maybe you also want to install a global exception handler (to safely shutdown your program).

And one other thing: Why do you check the length of your date string being exactly 10, when you only need 8 characters?

Community
  • 1
  • 1
Simon Kraemer
  • 5,700
  • 1
  • 19
  • 49