LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-31-2020, 10:40 AM   #1
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 192

Rep: Reputation: 31
C++ exception - what is wrong?


The e.what() prints rubbish. Why is that?
Code:
#include <iostream>
#include <sstream>
#include <exception>

class myexception : public std::exception
{
public:
    virtual const char* what() const throw()
    {
        return sstr.str().c_str();
    }
    std::ostringstream sstr;
};

int main() {
    try
    {
        myexception ex;
        ex.sstr << "very good";
        throw ex;
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << '\n';  // <-breakpoint
    }
    return 0;
}
I can still see "very good" at the breakpoint, but the output is just rubbish. Why is that?

Another question is, when is ex destroyed? Does it make sense to catch a reference rather than a copy?

Last edited by Jerry Mcguire; 03-31-2020 at 10:42 AM.
 
Old 03-31-2020, 11:56 AM   #2
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: CentOS 6 & 7
Posts: 3,340

Rep: Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906
ex is only defined in the try block. Declare it at before that at the beginning of main
 
Old 03-31-2020, 12:02 PM   #3
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 287

Rep: Reputation: Disabled
You have a dangling pointer. c_str is returning a pointer to the buffer in a temporary object - the return value of str().

If you changed ostringstream to a std::string and assigned to it you'd find the c_str() points to valid memory.
 
Old 03-31-2020, 04:50 PM   #4
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 192

Original Poster
Rep: Reputation: 31
Quote:
Originally Posted by smallpond View Post
ex is only defined in the try block. Declare it at before that at the beginning of main
Cannot. 'Attempting to reference a deleted function' at throw.

What is the right way of doing it?
 
Old 03-31-2020, 04:54 PM   #5
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,943

Rep: Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141
this might help

Code:
class myexception : public std::exception
{
public:
    virtual const char* what() const throw()
    {
        return sstr.str().c_str();
    }
    std::ostringstream sstr;
}ex; <---- declare here.
per http://www.cplusplus.com/doc/tutorial/exceptions/

Code:
class myexception: public exception
{
  virtual const char* what() const throw()
  {
    return "My exception happened";
  }
} myex;
 
Old 03-31-2020, 04:58 PM   #6
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 192

Original Poster
Rep: Reputation: 31
Quote:
Originally Posted by SoftSprocket View Post
You have a dangling pointer. c_str is returning a pointer to the buffer in a temporary object - the return value of str().

If you changed ostringstream to a std::string and assigned to it you'd find the c_str() points to valid memory.
I cannot understand the rationale behind combining the answer of both of you.
ex is declared only inside the try-block, then the content is destroy after reaching the catch-block. In that case neither ostringstream nor string is valid.

I have also tried catch(std::exception e) but it's not helping. ex is not copied to e.
 
Old 03-31-2020, 05:02 PM   #7
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 192

Original Poster
Rep: Reputation: 31
Quote:
Originally Posted by BW-userx View Post
this might help

Code:
class myexception : public std::exception
{
public:
    virtual const char* what() const throw()
    {
        return sstr.str().c_str();
    }
    std::ostringstream sstr;
}ex; <---- declare here.
per http://www.cplusplus.com/doc/tutorial/exceptions/

Code:
class myexception: public exception
{
  virtual const char* what() const throw()
  {
    return "My exception happened";
  }
} myex;
Same. 'Attempt to reference a deleted function'. And it doesn't make sense to declare a global variable.
 
Old 03-31-2020, 05:19 PM   #8
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 192

Original Poster
Rep: Reputation: 31
I cannot find any satisfactory example of throwing an object derived from std::exception on the Internet.
Anyone knows the right way of doing it? and perhaps explain why std::string works but std:stringstream won't.
 
Old 03-31-2020, 05:33 PM   #9
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 287

Rep: Reputation: Disabled
Quote:
Originally Posted by Jerry Mcguire View Post
I cannot understand the rationale behind combining the answer of both of you.
ex is declared only inside the try-block, then the content is destroy after reaching the catch-block. In that case neither ostringstream nor string is valid.

I have also tried catch(std::exception e) but it's not helping. ex is not copied to e.
The exception is copied to the catch clause. Try it and see:
Code:
#include <exception>
#include <string>
#include <iostream>
                                                                                                                        
class myexception : public std::exception
{
public:
    virtual const char* what() const throw()
    {
        return str.c_str();
    }
    std::string str;
};

int main() {
    try
    {
        myexception ex;
        ex.str = "very good";
        throw ex;
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << '\n';                                                                                      
    }
    return 0;
}
This demonstrates the dangle :

Code:
#include <sstream>
#include <iostream>

class Dangle {
        std::ostringstream ss;
public:
    Dangle (const char* s) {
        ss << s;
        std::cout << ss.str().c_str() << "\n";
    }

    const char* str() {
        return ss.str().c_str();
    }
};

int main () {
    Dangle d("Hello, world");
    std::cout << d.str() << "\n";

    return 0;
}
                                                                                                             ~

Last edited by SoftSprocket; 03-31-2020 at 07:40 PM. Reason: fix formatting
 
2 members found this post helpful.
Old 03-31-2020, 06:14 PM   #10
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (current), FreeBSD, Win10, It varies
Posts: 9,943

Rep: Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141Reputation: 2141
Quote:
Originally Posted by Jerry Mcguire View Post
Same. 'Attempt to reference a deleted function'. And it doesn't make sense to declare a global variable.
I have not delt with exceptions other than the default catching them.

Yet, having been investigating this issue I do not think OP is being written properly at all. trying to pass in a string into the exception via a data type declared within the class, then return it in that function that takes in no pharms even though it has a declared data type but no real means to return that in the function itself.

that example itself I posted in that link it does not do this, try to take an assignment then return it.

Where that exception return value within the exception function is suppose to be the error itself as defined by the programmer, to be return in that exception class function itself and not taking in from elsewhere so that it maybe over written by another means.

that sounds logical to me .

that is not to say one cannot over ride another exception catch to return the programmers error message rather then the "build in" one for an external means.

Last edited by BW-userx; 03-31-2020 at 06:23 PM.
 
Old 03-31-2020, 09:22 PM   #11
SoftSprocket
Member
 
Registered: Nov 2014
Posts: 287

Rep: Reputation: Disabled
The answer to what is wrong is in my earlier post - a dangling pointer.

A, perhaps canonical, example for extending exception:

Code:
#include <iostream>
#include <exception>

class TestException : public std::exception {
	std::string m_msg;
public:
	explicit TestException (std::string msg) : m_msg(msg) {}
	virtual ~TestException () throw () {}

	virtual const char* what () const throw () { return m_msg.c_str(); } 
};

int main () {
	try {
		throw TestException ("Hello, World");
	}
	catch (TestException& e) {
		std::cout << e.what() << "\n";
	}

	return 0;
}
 
Old 03-31-2020, 10:32 PM   #12
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 192

Original Poster
Rep: Reputation: 31
The dynamic content I try passing from the try-block to the catch-block is perhaps another info from an given API, or __FILE__,__LINE__ values. It could take several forms depending on the situations. That's why I try to format the what() content using the ostringstream. It should be a legitimate reason.

In the Dangle class example, I will interpret the problem as: the ss.str().c_str() returns a pointer pointing to the ss.str() instance, but which is destroyed after const char* str() {} exits.

Code:
    Dangle(const char* s) {
        ss << s;
        std::cout << ss.str().c_str() << "\n";
        std::cout << str() << "\n"; // <- This is what is wrong.
    }
The OP is modified to this to work:
Code:
#include <iostream>
#include <sstream>
#include <exception>

class myexception : public std::exception
{
public:
    virtual const char* what() const throw()
    {
        s = std::move(sstr.str());
        return s.c_str();
    }
    std::ostringstream sstr;
    mutable std::string s; // <-
};

int main() {

    try
    {
        myexception ex;
        ex.sstr << "very good";
        throw ex;
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << '\n';
    }
    return 0;
}
Thanks all.
 
Old 04-01-2020, 02:11 AM   #13
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,037

Rep: Reputation: 1463Reputation: 1463Reputation: 1463Reputation: 1463Reputation: 1463Reputation: 1463Reputation: 1463Reputation: 1463Reputation: 1463Reputation: 1463
Off: I don't know about C++ or exceptions, but I would start learning here: https://yosefk.com/c++fqa/exceptions.html
 
Old 04-01-2020, 08:28 AM   #14
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: CentOS 6 & 7
Posts: 3,340

Rep: Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906Reputation: 906
My apologies for misleading you. The original program was correct that the exception was still valid in the catch block and that e was a proper reference to it. I learned today that the str() returned from ostringstream is a temporary std::string.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
2domain but backingup the wrong one .. what am i doing wrong salimmeethoo Linux - Server 3 10-17-2007 10:43 AM
What is wrong with reiserfs? wrong free space mesh2005 Linux - General 1 05-03-2007 07:21 AM
help createing exception class from base STL exception qwijibow Programming 4 04-20-2005 05:23 AM
my time is wrong and calender is also wrong Paxmaster Linux - General 6 12-16-2004 12:46 AM
Runtime Exception vs. Exception mikeshn Programming 1 09-22-2002 05:33 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:42 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration