When I run this code:
#include <iostream>
#include <regex>
using namespace std;
main () {
const string source = "hello(abc_def)";
const regex regexp("he(l)lo.*");
smatch m;
if (regex_match(source, m, regexp)) {
cout << "Found, group 1 = " << m[1].str() << endl;
} else {
cout << "Not found" << endl;
}
const regex regexp2("hello\\((\\w+)\\)");
try {
if (regex_match(source, m, regexp2)) {
cout << "Found, group 1 = " << m[1].str() << endl;
} else {
cout << "Not found" << endl;
}
} catch(const exception& exc) {
cout << "Got exception: " << exc.what() << endl;
}
}
the output is:
Found, group 1 = el
terminate called after throwing an instance of 'std::regex_error'
what(): regex_error
accompanied by a dialog box that the program is crashing. I'm using g++ on Windows, 4.8.1 (yes, I specified -std=c++11), and I realize that the regular expression stuff was still experimental until 4.9, so that could explain why the first capture group is wrong and why it might have had a problem with the second regex. I'm still concerned about why it said it was throwing std::regex_error but my code didn't catch it. Changing exception& to regex_error& in the catch clause didn't change the behavior. Are all of these just library bugs, or did I do something wrong? I'm trying to relearn C++ after not having used it for 15 years or so (and also trying to learn C++11), so I'm concerned that I might have done something dumb.
The exception occurs in this line:
const regex regexp2("hello\\((\\w+)\\)");
And this line is not inside a "Try-catch" block.
Related
Does this quote from https://en.cppreference.com/w/cpp/language/function-try-block have a typo?
Reaching the end of a catch clause for a function-try-block on a destructor also automatically rethrows the current exception as if by throw;, but a return statement is allowed.
It seems hard to believe that a destructor automatically re-throws, when every article by every expert I've ever read says that destructors should never, ever throw under any circumstance. In fact, the example code above the quote shows an implicit throw from a constructor, not a destructor.
Therefore, I wonder, is the statement wrong and should have indicated that behavior for a constructor instead?
I had been reviewing this other StackOverflow article when I started thinking about this: C4297 warning in Visual Studio while using function-try-block (function assumed not to throw an exception but does). It already had an answer, but nobody questioned whether the quote was accurate in the first place.
The answer is no, it is not a typo.
The cppreference article did not show an example of a destructor function try block, so I crafted one myself and tested it. Below is the same code. I tested with Microsoft VS2019, using the v142 platform toolset and C++20 dialect.
If you execute this, an abort will be called, which is consistent with the warning that the compiler issues. This suggests that the function catch block does automatically re-throw, even for a destructor. If you uncomment the return statement, it will not throw. Although, I find that to be counter-intuitive, writing a return statement provides a workaround to prevent the implicit throw, just as the referenced StackOverflow article suggests.
#include <iostream>
#include <string>
struct S
{
std::string m;
S(const std::string& str, int idx) try : m(str, idx)
{
std::cout << "S(" << str << ", " << idx << ") constructed, m = " << m << '\n';
}
catch (const std::exception& e)
{
std::cout << "S(" << str << ", " << idx << ") failed: " << e.what() << '\n';
} // implicit "throw;" here
~S() try
{
if (m.length() > 5) {
throw std::exception("shouldn't have been that big!");
}
std::cout << "destroyed!" << std::endl;
}
catch (const std::exception& e)
{
//return;
}
};
int main()
{
S s1{ "ABC", 1 }; // does not throw (index is in bounds)
try
{
S s2{ "ABC", 4 }; // throws (out of bounds)
}
catch (std::exception& e)
{
std::cout << "S s2... raised an exception: " << e.what() << '\n';
}
try
{
S s3("123456", 0);
}
catch (std::exception& e)
{
std::cout << "S s2... raised an exception: " << e.what() << '\n';
}
}
I'm trying to build a lambda that wraps some input functions with some pre/post actions.
My code works fine and pre/post actions get called correctly if I try to wrap a regular function/lambda.
However, when I try to apply my decorating lambda to a function that it produced before, my program crashes after complaining that the inner function was freed at some point (this is confirmed by valgrind).
What puzzles me is that the crash depends on the compiler: the code works perfectly fine with Xcode 6 clang (clang-3.6 based), but crashes on linux using clang++-3.6 and g++4.8.4.
I've made a small program that reproduces the behaviour:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
typedef function<void(void)> NestedFn;
int main()
{
// Create a cfunction
auto lambdaFactory = [&](string title, NestedFn nestedFunc)
{
// title is copied to the new lambda
return [&, title]() {
cerr << "------------ START -----------" << endl;
cerr << "Inside: " << title << endl;
nestedFunc();
cerr << "------------- END ------------" << endl;
};
}
auto l1 = lambdaFactory("1", []() { cerr << "\tNest (1)" << endl; });
auto l2 = lambdaFactory("2", []() { cerr << "\tNest (2)" << endl; });
l1(); // Works ok, displays, START, 1, END
l2(); // Same here
auto dobble = lambdaFactory("Dobble", l1);
dobble(); // Display START, Inside Dobble, START,
// then crashes when trying to execute nestedFunc(), ie l1()
}
What did I get wrong in the variable scope management ? And is there any reason for this program not crashing using Apple's LLVM ?
EDIT
For the record, here is the correct lambdaFactory after the correction suggested by T.C. :
auto lambdaFactory = [&](string title, NestedFn nestedFunc)
{
return [&, title, nestedFunc]() {
cerr << "------------ START -----------" << endl;
cerr << "Inside: " << title << endl;
nestedFunc();
cerr << "------------- END ------------" << endl;
};
};
The lambda returned by a call to lambdaFactory captures nestedFunc by reference, but nestedFunc is a function argument passed by value, so it goes out of scope as soon as the call to lambdaFactory returns, resulting in a dangling reference.
And is there any reason for this program not crashing using Apple's LLVM ?
Undefined behavior is undefined. You are also likely using two different standard library implementations (libc++ on Mac/libstdc++ on linux), so there are likely differences in how everything is laid out etc.
Really can't figure out the reason for 'terminate called after throwing an instance of 'std::out_of_range''
std::cerr << std::string(s[0].first, s[0].second) << std::endl;
std::cerr << std::string(e[0].first, e[0].second) << std::endl;
std::cerr << std::string(s[0].first, e[0].second) << std::endl;
the above code return valid strings with matched results
boost::regex start(elementStartTag);
boost::regex end(elementEndTag);
boost::match_results<std::string::const_iterator> s, e;
if(!boost::regex_search(tmpTemplate, s, start)) {
dDebug() << "No start token: " << elementStartTag << " was found in file: " << templatePath();
std::cerr << "No start token: " << elementStartTag << " was found in file: " << templatePath() << std::endl;
return;
}
if(!boost::regex_search(tmpTemplate, e, end)) {
dDebug() << "No end token: " << elementEndTag << " was found in file: " << templatePath();
std::cerr << "No end token: " << elementEndTag << " was found in file: " << templatePath() << std::endl;
return;
}
//std::string::iterator si, ei;
// si = fromConst(tmpTemplate.begin(), s[0].second);
// ei = fromConst(tmpTemplate.begin(), e[0].first);
// std::cerr << std::string(si, ei) << "\t" << ss.str(); // return valid string
std::cerr << std::string(s[0].first, s[0].second) << std::endl;
std::cerr << std::string(e[0].first, e[0].second) << std::endl;
std::cerr << std::string(s[0].first, e[0].second) << std::endl;
std::cerr << "s[0].first - tmpTemplate.begin()\t" << s[0].first - tmpTemplate.begin() << std::endl;
std::cerr << "s[0].first - e[0].second\t" << s[0].first - e[0].second << std::endl;
//tmpTemplate.replace(fi, se, ss.str()); //also throws exeption
tmpTemplate.replace(s[0].first - tmpTemplate.begin(), s[0].first - e[0].second, "test"); // throws exeption
gcc version: 4.7.3 if it really matters
boost version: 1.52.0
UPDATE:
First:
The following equation is wrong s[0].first - e[0].second should be e[0].second - s[0].first - i wonder why nobody saw this (me also) - but consider it a typo, cause s[0].first - tmpTemplate.begin() return negative number anyway.
tmpTemplate defined and initialized as
std::string tmpTemplate= getTemplate();
Great - as i said s[0].first - tmpTemplate.begin() returns negative number
if tmpTemplate is defined and initialized as
std::string tmpTemplate(getTemplate().data(), getTemplate().length());
everything is fine.
Second:
stop boost::match_results uninitialized nonsense please read the regex_search documentation it says: "If i find no match i return false"
Third:
std::string tmpTemplate= getTemplate();
and
std::string tmpTemplate(getTemplate().data(), getTemplate().length());
DOES REALLY DIFFER.
Own Сonclusion:
It is ether a memory corruption which occurs else where in my code and i can't detect it with valgrind, or a bug which is not part of my code.
What are the contents of tmpTemplate, elementStartTag and elementEndTag? If the elementEndTag precedes the elementStartTag in tmpTemplate, then you'll definitely get an out_of_range error.
In the end, I'd recommend using just one regular expression, along the lines of:
boost::regex matcher( ".*(" + elementStartTag + ")(.*)(" + elementEndTag + ").*");
and then using boost::regex_match rather than search. This guarantees the order; it may cause problems if there is more than one matching element in the sequence, however. If this is an issue: you should use:
boost::regex_search( s[1].second, tmpTemplate.end(), e, end )
as the expression for matching the end.
I'm just learning how to use exceptions in C++ and have come across weird behavior in my "test" code. (excuse overly stupid questions like this one, please...it's NOT lack of research/effort, just lack of experience!) If I'm catching just the exception DivideByZero it works fine.
But introducing the second exception StupidQuestion makes the code not work exactly how I expected. How I wrote it below I thought it should take care of the DivideByZero exception if it needs to, and if not then check if StupidQuestion occurs, and if not just go back to the try clause and print the normal result. But if I input, say, a=3 and b=1, the program redirects to the DivideByZero try clause instead of the StupidQuestion one. The weird thing is, though, divide does seem to be throwing StupidQuestion (see via cout statement), but it's not catching right, as also seen by the absense of the cout statement.
#include <iostream>
#include <cstdlib>
using namespace std;
const int DivideByZero = 42;
const int StupidQuestion=1337;
float divide (int,int);
main(){
int a,b;
float c;
cout << "Enter numerator: ";
cin >> a;
cout << "Enter denominator: ";
cin >> b;
try{
c = divide(a,b);
cout << "The answer is " << c << endl;
}
catch(int DivideByZero){
cout << "ERROR: Divide by zero!" << endl;
}
catch(int StupidQuestion){
cout << "But doesn't come over here...?" << endl;
cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
}
system("PAUSE");
}
float divide(int a, int b){
if(b==0){
throw DivideByZero;
}
else if(b==1){
cout << "It goes correctly here...?" << endl;
throw StupidQuestion;
}
else return (float)a/b;
}
I was wondering if it had something to do with the fact that DivideByZero and StupidQuestion were both of type int, so I changed the code to make StupidQuestion be of type char instead of int. (So: const char StupidQuestion='F'; and catch(char StupidQuestion) were really the only things changed from above) And it worked fine.
Why isn't the above code working when the two exceptions have the same type (int)?
Instead of this
catch(int DivideByZero) {
cout << "ERROR: Divide by zero!" << endl;
}
catch(int StupidQuestion) {
cout << "But doesn't come over here...?" << endl;
cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
}
you are looking for
catch (int errval) {
if (errval == DivideByZero) {
cout << "ERROR: Divide by zero!" << endl;
}
else if (errval == StupidQuestion) {
cout << "ERROR: You are an idiot for asking a stupid question like that!" << endl;
}
else {
throw; // for other errors, keep searching for a handler
}
}
The variable name inside the catch clause is creating a new local variable, which has no relation to a global constant with the same name.
Also note that there will be no way to catch just one error number... but you can rethrow unknown errors as I show.
catch(int DivideByZero) { }
catch(int StupidQuestion) { }
Both catch blocks catch ints, they're just named differently. Only the first one can ever be entered, the second one is dead code.
When choosing a handler for an exception only type is taken into account, and neither values nor addresses (addresses of variables are not applicable here at all because of how exceptions work), also names of variables do not exist after compilation.
The first appropriate handler for the exception is always chosen.
Please look my answer to another question for details: https://stackoverflow.com/a/45436594/1790694
I wrote a very simple solution however someone laughed and found a flaw as shown here http://ideone.com/IcWMEf
#include <iostream>
#include <ostream>
#include <functional>
#include <exception>
using namespace std;
// Wrong scope(failure)
class FailBlockT
{
typedef function<void()> T;
public:
T t;
FailBlockT(T t)
{
this->t=t;
}
~FailBlockT()
{
if (std::uncaught_exception())
{
t();
}
}
};
struct Test
{
~Test()
{
try
{
FailBlockT f([]()
{
cout << "failure" << endl;
});
// there is no any exception here, but "failure" is printed.
// See output below
}
catch(...)
{
cout << "some exception" << endl;
}
}
};
int main()
{
try
{
Test t;
throw 1;
}
catch(int){}
return 0;
}
In short the problem is my code looks at std::uncaught_exception(). When an exception is thrown and a normal destructor is executed. If i use scope failure there it will look at std::uncaught_exception() and think the object scope is lost due to exception rather then simply walking out of scope.
I can't think of any good solutions to differentiate leaving scope normally VS having an exception thrown IN it. Yes i know throwing is a bad idea in dtors BUT thats why I fail to notice this problem, because I never throw in exceptions.
How do I differentiate/solve this?
No exception was thrown but it thinks it has.
An exception was thrown, just not from right there.
There is no mechanism in C++11 to ask, "Was an exception thrown from code just below me, but not from code elsewhere in the call-stack?" std::uncaught_exception is doing exactly what it is supposed to do: say whether there is an exception currently in the process of being resolved at the time the function is called. And there is, so it returns true.
C++17 adds std::uncaught_exceptions (note the plural), which can be used to detect the difference. With such a tool, you can make your FailBlock object work:
template<typename Func>
class FailBlockT
{
private:
int e_count_;
T t_;
public:
FailBlockT(T t) : e_count_(std::uncaught_exceptions()), t_(t) {}
FailBlock(const FailBlock &) = delete; //The type should not be mobile.
~FailBlockT()
{
if (std::uncaught_exceptions() != e_count_)
{
t_();
}
}
};
std::uncaught_exceptions() returns the number of exceptions that are provoking stack unwinding at the time the call was made. If the number is the same during the constructor and destructor of an object (assuming it's a stack object), then the destructor is not being called due to an exception being thrown through where this type was used.
But without this tool, it, there's not much you can do to differentiate between an exception provoking the exiting of the scope rather than exiting a scope when exception unwinding just happens to be going on. So you're going to have to bite the bullet and catch the exception like everyone else.
Or just don't put this FailBlock thing in destructors. It seems to me that those should go directly into regular functions that can actually throw (and destructors should never throw). It seems to me that you're worried about a corner case that doesn't make any real sense.
I can't think of any good solutions to differentiate leaving scope normally VS having an exception thrown IN it.
Check stack_unwinding library - I have implemented scope(failure) and scope(success) features in C++.
It is based on platform specific function uncaught_exception_count. It is similar to std::uncaught_exception from standard library, but instead of boolean result it returns unsigned int showing current count of uncaught exceptions.
Currently it is tested on {Clang 3.2, GCC 3.4.6, GCC 4.1.2, GCC 4.4.6, GCC 4.4.7, MSVC2005SP1, MSVC2008SP1, MSVC2010SP1, MSVC2012} x {x32, x64}.
In C++11 folowing syntax is available:
try
{
int some_var=1;
cout << "Case #1: stack unwinding" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
throw 1;
} catch(int){}
{
int some_var=1;
cout << "Case #2: normal exit" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
}
In C++98 it is a bit more noisier:
try
{
cout << "Case #1: stack unwinding" << endl;
BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END
SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END
throw 1;
} catch(int){}
{
cout << "Case #2: normal exit" << endl;
BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END
SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END
}
Also, library has UNWINDING_AWARE_DESTRUCTOR feature. Example:
struct DestructorInClass
{
UNWINDING_AWARE_DESTRUCTOR(DestructorInClass,unwinding)
{
cout << "DestructorInClass, unwinding: "
<< ( unwinding ? "true" : "false" ) << endl;
}
};
However, there are some cases where UNWINDING_AWARE_DESTRUCTOR may give wrong results (though scope(success) and scope(failure) features are not affected by such issues).