I have the following function:
void filesys::create(char * pathname, char type) {
//char * msg;
//sprintf(msg, "create pathname: %s type: %c", pathname, type);
throw filesys::BadRequest();
}
When the first two lines are commented out as shown, the exception propagates and is caught by the calling function. When I uncomment these lines, I immediately get a propagation error:
libc++abi.dylib: terminating with uncaught exception of type filesys::BadRequest: bad req
Exception definition within filesys class:
struct BadRequest : public std::exception {
const char * what () const throw () {
return "bad req";
}
};
Catch block:
try {
char * response = serve_request(decrypted);
send_msg(connectionfd, response);
} catch (filesys::BadRequest& e) {
cout << "hello?";
}
Related
I want to catch an exception to further specify the error message, then throw a new exception with that extended message. However, that causes garbage output. Why?
Here's an MWE:
#include <iostream>
#include <string>
#include <exception>
class myError : public std::exception
{
private:
std::string m_error;
public:
explicit myError( const std::string& error ) :
m_error { error }
{}
explicit myError( const char* error ) :
m_error { error }
{}
const char* what() const noexcept override
{
//return m_error.c_str();
return ("My error: " + m_error).c_str();
}
};
int main()
{
try{
try{
throw myError ( "Error message" );
} catch ( const std::exception& e ) {
throw myError( e.what() );
}
} catch ( const std::exception& e ) {
std::cout << e.what() << "\n";
}
return 0;
}
I would expect the output to be "My error: My error: Error message", but instead, it's a short sequence of random characters, presumably until a \0 is hit.
If I do not add a message inside myError::what() (i.e. the line that's commented out), then the output is simply "Error message", so everything works as expected.
Why is that happening?
I'm running gcc 8.1.0 on Windows, with x86_64-posix-seh-rev0 as the install options.
And I'm somewhat aware of nested_exception and that I'm losing some information on the trace etc.
EDIT: As a workaround, adding the message "My error" inside the constructor produces the expected output:
explicit myError( const std::string& error ) :
m_error { "My error: " + error }
{}
explicit myError( const char* error ) :
m_error { "My error: " + std::string{ error } }
{}
const char* what() const noexcept override
{
return m_error.c_str();
}
So something seems to be wrong with return ("My error: " + m_error).c_str();.
In:
return ("My error: " + m_error).c_str();
... c_str() returns a pointer to the internal buffer of the temporary string created by the concatenation. This string's lifetime ends immediately after the return statement, making the returned pointer dangling and its use undefined.
This is a c++ program to calculate average, and grade using 5 marks.
If marks entered are greater than 100 or less than 0, student exception should be thrown.
#include<iostream>
#include<exception>
using namespace std;
class lessex:public exception
{
public:
void what()
{
cout<<"Mark less than 0"<<endl;
}
};
class morex:public exception
{
public:
void what()
{
cout<<"Mark greater than 100"<<endl;
}
};
class student
{
string name;
string rollno;
int marks[5];
double avg;
char g;
public:
void get();
void aveg();
void grade();
void print();
};
void student::get()
{
cin>>name;
cin>>rollno;
for(int i=0;i<5;i++)
{
try{
cin>>marks[i];
if(marks[i]>100)
{
morex d;
throw d;
}
}
catch(morex &e)
{
/*e.what();*/
throw ;
}
try{
if(marks[i]<0)
{
lessex d;
throw d;
}
}
catch(lessex &e)
{
/*e.what();*/
throw ;
}
}
}
void student::aveg()
{
int sum=0;
for(int i=0;i<5;i++)
{
sum=sum+marks[i];
}
avg=sum/5;
}
void student::grade()
{
if(avg>90)
g='S';
else
g='Z';
}
void student::print()
{
cout<<name<<endl;
cout<<rollno<<endl;
cout<<g<<endl;
}
int main()
{
student s;morex e;lessex e1;
try{
s.get();
}
catch(morex &e)
{
e.what();
}
catch(lessex &e1)
{
e1.what();
}
s.aveg();
s.grade();
s.print();
return 0;
}
However, my program does not successfully exit after encountering exception in the main function.
Why is it continuing with s.aveg,grade,etc.
Why is my program not exiting after encountering exception-from main function? Why is it continuing with s.aveg,grade,etc.
You catch the exception, and then leave the catch block. Execution continues normally after that. Exceptions aren't re-thrown automatically at the end of a handler's block. That would maddening, what's the point of catching if you can't handle the error and continue running?
If you want the exception re-thrown, you need to add an explicit throw; in the handler. Like you already do in student::get(). Or just not have a try-catch block there. The program will terminate without "s.aveg,grade,etc." being executed.
Or, assuming you intent is not terminate, but to exit gracefully without executing other functions, you can do as user4581301 suggested. Move those function calls into the try block. That way, if an exception is thrown before their execution, they will not run before or after the handler.
You continue execution, without exiting, after catching the exception, and that's why the program isn't exiting.
First, you should follow the convention that what returns a string and doesn't print anything:
class lessex : public exception
{
public:
const char* what() const noexcept override
{
return "Mark less than 0";
}
};
class morex : public exception
{
public:
const char* what() const noexcept override
{
return "Mark greater than 100";
}
};
Then, you're overcomplicating things rather a lot in get;
void student::get()
{
cin >> name;
cin >> rollno;
for(int i = 0; i < 5; i++)
{
cin >> marks[i];
if (marks[i]>100)
{
throw morex();
}
if(marks[i]<0)
{
throw lessex();
}
}
}
and exceptions shouldn't be used like error codes and caught after each potentially throwing call, you normally write the "happy path" (the assumed-to-be-error-free path) and handle exceptions outside it:
int main()
{
try
{
// This part handles the normal case, assuming that all goes well.
student.s;
s.get();
s.aveg();
s.grade();
s.print();
}
// This part handles the exceptional case when something goes wrong.
catch (std::exception& ex)
{
std::cerr << ex.what();
}
}
(Your design is somewhat questionable since throwing from get can leave the object in an invalid state. You might want to rethink it.)
It is continuing because after you catch the exception you don't do anything about it. You have to specify what you would do inside the catch block when the specific exception is thrown.
Alternatively you could also move the other functions like s.aveg(); s.grade(); s.print(); inside try{
s.get();
}
This will prevent the aveg, grade and print functions from stop executing once an exeption is hit
I use try{} catch(){} to handle errors in a function which return a template type.
T get (int iOffset) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return a;
}
The function would first call checkIndex to check whether the input is out of range and throw an error if so.
However, I don't want the outside get return any value if checkIndex throws an error, because the returned value may be used by other functions or printed out incorrectly. If I put a return in the catch block, I don't know what to return since it's a template. If I don't, the codes following the catch block will still get executed and therefore return a value.
Is there any way to do that? I'm new to C++ and wondering how people usually do the error handling in this condition? THanks!
However, I don't want the outside get return any value if checkIndex throws an error, because the returned value may be used by other functions or printed out incorrectly.
You can always re-throw the exception after logging
T get (int iOffset) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
throw; // Just re-throw the exception
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return a;
}
You can also use optional for this situation. One of idea of this construct was to indicate that value cannot be set correctly because of some mistakes.
std::optional< T > get (int iOffset ) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
return std::optional< T >();
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return return std::optional< T >( a );
}
Using of such function can look like this:
auto result = get( someOffset );
if( result )
{
// correct, processing result
}
One of the easiest way is first to decide: What exactly should your get() return if it cannot return the 'proper' value?
In many cases it is just 0, or -1, or some other special value.
And then the code become very simple:
T get (int iOffset) const
{
T a;
try {
checkIndex(iOffset);
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
a = m_ptBuff[index];
}
catch (char const* msg) {
a = special_value_for_errors;
std::cout << msg << std::endl;
}
return a;
}
I am trying to call a function from my Calculator class in a test class.
How do I assert that exception message thrown by Calculator equals to one I expect?
My calculator code:
void Calculator::add() {
if (_stack.empty()) {
throw std::runtime_error("empty stack");
}
else if (_stack.size() == 1) {
throw std::runtime_error("Wrong Value");
}
else if (_stack.size() > 2) {
throw std::runtime_error("Wrong Value");
}
else {
double res = this->pop() + this->pop();
this->push(res);
}
}
Here is my test class:
TEST_METHOD(should_throw_error_if_stack_is_empty) {
Assert::AreEqual([] {
Calculator* myCalculator = new Calculator();
try {
myCalculator->add();
}
catch (std::runtime_error const& ex)
{
return (ex.what());
}
}, "empty stack");
}
The reason it does not work: Value returned by lambda function has type const char* while my expression type is const char. How should I do it?
And is the approach I follow a good practice in general? I mean catching the exceptions thrown by class in a unit test?
I am trying to compile C++ code with CLANG++ as front end and backend as LLVM.
The version is 3.0.
There seems to be a problem with exception handling. Whenever the code throws an exception, the program just terminates with message that "Termination after throwing an exception".
Here is one of the sample code I tried with CLANG ++ .
struct A {};
struct B : virtual A {};
struct C : virtual A {};
struct D : virtual A {};
struct E : private B, public C, private D {};
extern "C" void abort ();
void fne (E *e)
{
throw e;
}
void check(E *e)
{
int caught;
caught = 0;
try { fne(e); }
catch(A *p) { caught = 1; if (p != e) abort();}
catch(...) { abort(); }
if (!caught) abort();
caught = 0;
try { fne(e); }
catch(B *p) { abort ();}
catch(...) { caught = 1; }
if (!caught) abort();
caught = 0;
try { fne(e); }
catch(C *p) { caught = 1; if (p != e) abort();}
catch(...) { abort(); }
if (!caught) abort();
caught = 0;
try { fne(e); }
catch(D *p) { abort ();}
catch(...) { caught = 1; }
if (!caught) abort();
return;
}
int main ()
{
E e;
check (&e);
check ((E *)0);
return 0;
}
I am quite new to LLVM so do not have much idea about it. Also does it have anything related to Exception Handling table generation by LLVM.
The above problem continues for any code.
I have compiled the above code on Linux machine.
Also I tried putting printf on every catch clause but no response. So it seems that when exception was thrown , no matching catch was found for the exception and it led to call of terminate funciton
Seeing your other question... If you're on arm/linux - then such result is expected. The support for EH is not finished there, so, it might be arbitrary broken.