This code throws an exception when I enter "Timmy" as the name. I'm really not sure of the mechanism but why does it print out "abracadabra" and not "Timmy". One thing I'm sure of though is that there is no magic going on here!
This is the short code
#include <iostream>
using namespace std;
#include <string>
#include <cstdlib>
string enterName();
void checkName(string);
int main()
{
string someName = "abracadabra";
try {
someName = enterName();
}
catch(const char* error) {
cout << "main function says: "<<error <<endl;
}
cout << "Name: "<<someName<<endl;
return 0;
}
string enterName()
{
string s;
cout<<"Enter a name: ";
cin >> s;
cout<<endl;
try {
checkName(s);
}
catch(const char* err) {
cout << "middle man says: "<<err <<endl;
throw "rtetfrer";
}
return s;
}
void checkName(string name)
{
if (name == "Timmy")
throw "Help, Timmy's been kidnapped by a giant squid!";
}
You are throwing an exception, so the function never returns:
void checkName(string name)
{
if (name == "Timmy")
//This throws an exception, so the function exits immediately
throw "Help, Timmy's been kidnapped by a giant squid!";
}
That exception is caught here:
try {
checkName(s);
}
catch(const char* err) {
//This will be the exception that timmy is caught
cout << "middle man says: "<<err <<endl;
//This will throw an exception and immediately exit the function
throw "rtetfrer";
}
//This will never be called
return s;
And the new exception will be caught here:
catch(const char* error) {
cout << "main function says: "<<error <<endl;
}
But since checkName never returned a value, somename will still be magic
enterName(); throws an exception before the assignment to someName is made. Hence someName retains its original value.
(In a little more detail: enterName() calls checkName(). checkName() throws an exception since name is "Timmy". enterName() throws "rtetfrer". Why not verify with your debugger?)
In order to assign a value to someName, c++ must first evaluate the expression on the left side. That is the result of the function enterName. Now during the execution of this function an exception is thrown. When this happens the execution jumps right to the catch clause(skipping the return clause of the function and then the assignment of someName to this return value), thus you never assign a different value to someName.
Use a debugger to follow the execution flow in an easier manner.
Related
<C++>In exception handling, do you need to know what exception and where an exception is going to occur? Can you make a code which will print and notify us that an exception occurred somewhere in the program. I mean I have a program in which I don't know if an exception will occur or not, if one was to occur, then it will print to notify us.
Exception handling is something you should design for, and in fact it works very well together with RAII (https://en.cppreference.com/w/cpp/language/raii).
(Notr On embedded platforms using exceptions, is not so popular because of some runtime overhead). What I personally like about exceptions is that it separates error handling from the normal program flow (there will be hardly any if then else checks when done right)
// Exception handling should be part of your overal design.And many standard library functions can throw exceptions, It is always up to you where you handle them.
#include <iostream>
#include <string>
#include <stdexcept>
int get_int_with_local_exception_handling()
{
do
{
try
{
std::cout << "Input an integer (local exception handling, enter a text for exception): ";
std::string input;
std::cin >> input;
// stoi is a function that can throw exceptions
// look at the documentation https://en.cppreference.com/w/cpp/string/basic_string/stol
// and look for exceptions.
//
int value = std::stoi(input);
// if input was ok, no exception was thrown so we can return the value to the client.
return value;
}
// catch by const reference, it avoids copies of the exception
// and makes sure you cannot change the content
catch (const std::invalid_argument& e)
{
// std::exceptions always have a what function with readable info
std::cout << "handling std::invalid_argument, " << e.what() << "\n";
}
catch (const std::out_of_range& e)
{
std::cout << "handling std::out_of_range, " << e.what() << "\n";
}
} while (true);
}
int get_int_no_exception_handling()
{
std::cout << "Input an integer (without exception handling, enter a text for exception): ";
std::string input;
std::cin >> input;
int value = std::stoi(input);
return value;
}
int main()
{
try
{
// this function shows you can handle exceptions locally
// to keep program running
auto value1 = get_int_with_local_exception_handling();
std::cout << "your for input was : " << value1 << "\n";
// this function shows that exceptions can be thrown without
// catching, but then the end up on the next exception handler
// on the stack, which in this case is the one in main
auto value2 = get_int_no_exception_handling();
std::cout << "your input was : " << value1 << "\n";
return 0;
}
catch (const std::exception& e)
{
std::cout << "Unhandled exception caught, program terminating : " << e.what() << "\n";
return -1;
}
catch (...)
{
std::cout << "Unknown, and unhandled exception caught, program terminating\n";
}
}
Yes and no.
No, because any exception thrown via throw some_exception; can be catched via catch(...).
Yes, because catch(...) is not very useful. You only know that there was an excpetion but not more.
Typically exceptions carry information on the cause that you want to use in the catch. Only as a last resort or when you need to make abolutely sure not to miss any excpetion you should use catch(...):
try {
might_throw_unknown_exceptions();
} catch(std::exception& err) {
std::cout << "there was a runtime error: " << err.what();
} catch(...) {
std::cout << "an unknown excpetion was thrown.";
}
The C++ standard library uses inheritance only sparingly. Exceptions is only place where it is used extensively: All standard exceptions inherit from std::exception and it is good practice to inherit also custom exceptions from it.
I have used custom terminate handler which works fine if I call throw with a type or explicitly call terminate(), but if I use rethow i.e throw; , the custom terminate handler is not called, only default terminate handler is called causing the program to abort. Code confirms to C++03. Could anyone help me to find out the problem ? Thank you in advance
#include <iostream>
#include <exception>
using namespace std;
void myunexpected() {
cerr << "CUSTOM unexpected handler called ------ \n";
throw 0; // throws int (in exception-specification)
}
void myterminate () {
cerr << "CUSTOM terminate handler called ------ \n";
//abort(); // forces abnormal termination
exit(0);
}
void myfunction() throw (int) {
throw 'x'; // throws char (not in exception-specification)
}
int main(void) {
set_unexpected(myunexpected);
set_terminate(myterminate);
int a = 1;
try{
try {
myfunction();
}
catch (int) {
cerr << "caught int\n";
throw string("sree");
}
catch (...) { cerr << "caught some other exception type\n"; }
}
catch (string& s)
{
cerr << a << "caught STRING " << s << endl;
//throw 0; //ok --> implicitly calls terminate()-->myterminate
//terminate(); //ok --> explicitly calls terminate()-->myterminate
throw; //--------- Calls default throw Why ???
}
return 0;
}
OUTPUT
CUSTOM unexpected handler called ------
caught int
1caught STRING sree
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
--------------------------------
Process exited after 8.238 seconds with return value 255
Press any key to continue . . .
Can I make something like this?
#define N_VALID "is not a valid ID"
...
throw N_valid;
...
catch(char *message){
fprintf(stderr,"%s",message);}
Yes, except that you are throwing a const char *, not a char *: https://ideone.com/UsnitG
#include <iostream>
using std::cout; using std::endl;
#define N_VALID "is not a valid ID"
void function_throws()
{
throw N_VALID;
}
int main()
{
try
{
function_throws();
}
catch(const char *message) // <= Note the const here!
{
cout << message << endl;
}
}
However, Joel is correct that you should avoid doing this. If you really want to use a macro here, try using it as an argument to a std::exception object: https://ideone.com/Dsx1RF
void function_throws()
{
throw invalid_argument(N_VALID);
}
int main()
{
try
{
function_throws();
}
catch(const invalid_argument& ex)
{
cout << "invalid_argument: " << ex.what() << endl;
}
}
Yes.
#define N_VALID "is not a valid ID"
throw N_VALID;
throw "is not a valid ID";
The bottom two lines above are literally identical in the eyes of the compiler, once pre-processing has completed.
This is legal but immoral. You should ALWAYS throw an object so that your clients can handle your errors individually, rather than having a giant if statement in one catch.
The #define directive works by replacing a tag with another tag in your code before the application is compiled. Thus, if you can do this:
throw "is not a valid ID";
you can do this:
throw N_VALID;
It should work. Remember, the pre-processsor runs before the compiler and will replace the N_VALID with "is not a valid ID"
I have the following chunk of code in my constructor (This is just an example, the question isn't about split, rather about throwing a generic exception. Also, Boost library can't be used.
Transfer::Transfer(const string &dest){
try{
struct stat st;
char * token;
std::string path(PATH_SEPARATOR) // if it is \ or / this macro will solve it
token = strtok((char*)dest.c_str(), PATH_SEPARATOR) //
while(token != NULL){
path += token;
if(stat(path.c_str(), &st) != 0){
if(mkdir(path.c_str()) != 0){
std:string msg("Error creating the directory\n");
throw exception // here is where this question lies
}
}
token = strtok(NULL, PATH_SEPARATOR);
path += PATH_SEPARATOR;
}
}catch(std::exception &e){
//catch an exception which kills the program
// the program shall not continue working.
}
}
What I want is to throw an exception if the directory does not exist and it can't be created. I want to throw a generic exception, how could I do it in C++?
PS: dest has the following format:
dest = /usr/var/temp/current/tree
Please check this answer. This explains how to use your own exception class
class myException: public std::runtime_error
{
public:
myException(std::string const& msg):
std::runtime_error(msg)
{}
};
void Transfer(){
try{
throw myException("Error creating the directory\n");
}catch(std::exception &e){
cout << "Exception " << e.what() << endl;
//catch an exception which kills the program
// the program shall not continue working.
}
}
Also, if you don't want your own class, you can do this simply by
throw std::runtime_error("Error creating the directory\n");
Your usage of strtok is incorrect - it needs a char* because it modifies the string, but it is not permitted to modify the results of a .c_str() on a std::string. The need to use a C style cast (which here is performing like a const_cast) is a big warning.
You can neatly sidestep this and the path separator portability stuff by using boost filesystem, which is likely to appear in TR2 whenever that's release. For example:
#include <iostream>
#include <boost/filesystem.hpp>
int main() {
boost::filesystem::path path ("/tmp/foo/bar/test");
try {
boost::filesystem::create_directories(path);
}
catch (const boost::filesystem::filesystem_error& ex) {
std::cout << "Ooops\n";
}
}
Splits the path on the platform's separator, makes the directories if needed or throws an exception if it fails.
I have a sample code to modify and throw exception handling. The problem is even after I threw an exception, the code still returns a random 0. I have spent some time trying to figure out why I still have a 0 returned but I could not find the answer. Does anyone have an idea why the code behaves like this?
#include <stdexcept>
#include <iostream>
#include <string>
using namespace std;
struct myException_Product_Not_Found : exception
{
virtual const char* what() const throw() {
return "Product not found";
}
} myExcept_Prod_Not_Found;
int getProductID(int ids[], string names[], int numProducts, string target) {
for (int i=0; i<numProducts; i++) {
if(names[i] == target)
return ids[i];
}
try {
throw myExcept_Prod_Not_Found;
}
catch (exception& e) {
cout<<e.what()<<endl;
}
}
// Sample code to test the getProductID function
int main() {
int productIds[] = {4,5,8,10,13};
string products[] = {"computer","flash drive","mouse","printer","camera"};
cout << getProductID(productIds, products, 5, "computer") << endl;
cout << getProductID(productIds, products, 5, "laptop") << endl;
cout << getProductID(productIds, products, 5, "printer") << endl;
return 0;
}
getProductID doesn't throw an exception. You catch the exception you do throw before getProductID has a chance to throw it. As such, you return ... well, nothing. The functions ends without you calling return.
If you had turned on your compiler's warnings* (as should should be doing), the compiler should warn with a message like control reaches end of non-void function. g++ appears to return zero in this instance, but returning zero is probably undefined behaviour.
If you want a function to throw an exception, don't catch the exception you've thrown inside of the function. Move the catch to the outside.
int getProductID(...) {
...
throw myExcept_Prod_Not_Found;
}
string product = "computer";
try {
cout << getProductID(productIds, products, 5, product) << endl;
} catch (exception& e) {
cout << "Can't find product id for " << product << ": " << e.what() << endl;
}
* — To turn on warnings in g++, -Wall is a good starting point. #Tomalak Geret'kal suggests -Wall -Wextra -std=c++98 -pedantic or -Wall -Wextra -std=c++0x -pedantic.
try {
throw myExcept_Prod_Not_Found;
}
catch (exception& e) {
cout<<e.what()<<endl;
}
Here you're throwing an exception and then immediately catching it. The exception message is output to console and then execution of your function continues as normal... except you have no value to return.
So, the result of that function call is unspecified, and you're seeing some arbitrary rubbish from memory as well as invoking undefined behaviour.
Instead, just let the exception propogate right up the callstack by not catching it: it'll lead your program to terminate (possibly without actually unrolling, incidentally):
throw myExcept_Prod_Not_Found;