`

c++ - rethrow a exception gotchas

    博客分类:
  • c++
c++ 
阅读更多

As in my prevoius example in  java - common practice to rethrow exceptions, we have seen that it is always good to rethrow an new exception with the old exception as its inner exception, and it is not too bad after to just throw the exception that you have just catched (only you loose the information that the original exception has).

 

in C++, there is  a special syntax to rethrow the exception that has been caught. which is just call "throw" without any argument, here is what you do 

 

try {
  // statements.
} catch (const exception& ex_)  {
  throw;
}

 because of the "const reference &" syntax in the code above. 

 

Since not all C++ classes has the necessary call stack support,  we might not be able to show every clearly the major diference in terms of the call stack. 

 

class UnsupportedException : public exception {
public:
	 const exception * const innerException() {
		return _innerException;
	}

	UnsupportedException(const char*  message_, const exception * const innerException_) : exception(message_), message(message_), _innerException(innerException_) {
	}

	UnsupportedException(const UnsupportedException& rhs) : 
		exception(rhs.message), message(rhs.message), _innerException(rhs._innerException)
	{
	}
	/** one thing is missing which is called delegaing constructor */
	virtual const char * what() { 
		return ((const UnsupportedException *) this)->what();
	}

	virtual const char * what() const { 
		char* b = new char[100];
		strcpy(b, message);
		if (_innerException != NULL) { 
			strcat(b, "cause by \n");
			strcat(b, _innerException->what());
		}
		return b;
	}



private:
	const char * message;
	const exception *  const _innerException;
};


void generateException() 
{
	const UnsupportedException exc = UnsupportedException("not implemented 'generateException'", new exception("Inner exception"));
	throw exc;
}


void rethrowException() 
{
	try {
		generateException();
	} catch (exception& ex_) { 
		throw;
	}
}

void rethrowDestroyOriginalInfo() { 
	try { 
		generateException();
	} catch (const exception & ex_)  {
		throw ex_;
	}
}


void rethrowExceptionWithInnerException() 
{
	try {
		generateException();
	} catch (exception& ex_) { 
		throw UnsupportedException("wrapped new UnsupportedException", new UnsupportedException(dynamic_cast<const UnsupportedException &>(ex_)));
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	try { 
		rethrowException();
	}
	catch (const UnsupportedException & ex_) {
		cout <<  "in catch (const exception & ex_)" << endl;
		const char * what = ex_.what();
		cout << what << endl;
	}

	cout <<  "============================ " << endl;

	try { 
		rethrowDestroyOriginalInfo();
	}
	catch (const UnsupportedException & ex_) {
		cout <<  "in catch (const exception & ex_)" << endl;
		const char * what = ex_.what();
		cout << what << endl;
	}
	catch (const exception & ex_)  {
		cout <<  "in const exception & ex_" << endl;
		const char * what = ex_.what();
		cout << what << endl;
	}

	cout <<  "============================ " << endl;

	try { 
		rethrowExceptionWithInnerException();
	}
	catch (const UnsupportedException & ex_) {
		cout <<  "in catch (const exception & ex_)" << endl;
		const char * what = ex_.what();
		cout << what << endl;
	}
	catch (const exception & ex_)  {
		cout <<  "in const exception & ex_" << endl;
		const char * what = ex_.what();
		cout << what << endl;
	}
	return 0;
}

 

and the output of the running the above program is like this:  

 

in catch (const exception & ex_)
not implemented 'generateException'cause by
Inner exception
============================
in const exception & ex_
not implemented 'generateException'
============================
in catch (const exception & ex_)
wrapped new UnsupportedExceptioncause by
not implemented 'generateException'cause by
Inner exception
 

As you can see, with the "throw;" the standard way of rethrowing excpetion, it has the correct error messages and with the "throw ex;", the real type of exception may be lost in the catch handler (you can see the second output", the third is what we try to replicate for the c# or java style of throwing exception - which to be honest, I am not sure if that is indeed what we really what we wantted to do in C++;

分享到:
评论

相关推荐

    C++Exception 异常处理 源码

    9. **`std::current_exception`和`std::rethrow_exception`**: 这两个函数用于获取当前活跃的异常对象和重新抛出它。这对于在异常处理过程中进行调试或记录信息非常有用。 10. **异常与析构函数**: 当异常发生...

    testers-rethrow

    测试者一掷千金 描述 不同测试人员: 将异常抛出另一个异常。 将异常抛出到catch中-相同的异常。 抛出异常到catch中-两种不同的异常。 将日志错误扔到catch中。... 将日志错误扔到catch中。... :)

    C++中的意外处理技术

    此外,`std::current_exception`可以获取当前正在传播的异常,而`std::rethrow_exception`则可以重新抛出已捕获的异常。 异常处理的一个最佳实践是尽量减少异常穿透,即避免在析构函数中抛出异常,因为这可能会导致...

    Java throw Exception实现异常转换

    在上面的代码中,我们使用RethrowException将IOException转换为unchecked exception。 六、结论 Java throw Exception实现异常转换是一种有效的异常处理机制,它可以将checked exception转换为unchecked exception...

    C++模拟题5答案.docx

    throw、catch、rethrow D. try、catch、except 答案:A 解析:(P253)C++的异常处理机制由try、catch和throw关键字构成。try块包含可能抛出异常的代码,catch块用于捕获和处理异常,而throw用于抛出异常。 13. C++...

    实验7(异常).zip

    此外,`std::current_exception`函数可以获取当前正在处理的异常对象的引用,而`std::rethrow_exception`则可以再次抛出该异常,这对于在不同`catch`块之间传递异常非常有用。 在实验中,你可能会编写一段代码,...

    Qt程序crash信息的捕捉与跟踪Demo

    在该函数中,我们可以使用`std::rethrow_exception()`来重新抛出异常,以便在调试器中查看堆栈信息。同时,我们也可以在这个函数中收集其他有用的信息,如进程ID、线程ID和当前时间戳,这些都可以帮助我们追踪问题。...

    Bjarne Stroustrup的FAQ:C++的风格与技巧

    如果想要恢复异常之前的执行流程,可以在try块中使用`noexcept`指定或在catch块中使用`rethrow`来重新抛出异常。 ##### (17) 为什么C++中没有相当于realloc()的函数? C++没有直接提供`realloc()`这样的函数,因为...

    The C++ Programming Language(ch 14)

    #### 14.5 再抛出 [except.rethrow] 再抛出是指在捕获异常后,选择将异常重新抛出给上层处理的过程。这对于那些不需要立即处理异常的情况很有用,例如在构造函数中发生异常时,可以将其重新抛出以便在更高层次上...

    ebt_limit.rar_limit

    在C++中,rethrow操作用`throw;`语句表示,没有指定任何表达式。 接下来,我们来看文件名中的关键词"limit"。这可能指的是在处理异常时的限制条件,比如异常处理的范围、资源限制或者是特定情况下不允许抛出异常的...

    cps-future:C ++ FuturePromises实现,大致基于Future.pm

    错误处理基于异常的错误处理依赖于std :: current_exception和std :: rethrow_exception。 如果您预计会遇到许多错误情况,这些速度可能会很慢。其他实施std :: future 理想情况下,我们可以将核心库功能用于期货...

    Java_Programming_Exception_Example_code.rar_advanced java_java p

    在"Java高级编程RethrowException代码.rar"中,我们可以看到如何处理和重新抛出异常。在Java中,`try-catch`块用于捕获和处理异常。`try`块包含可能抛出异常的代码,`catch`块用于捕获并处理这些异常。如果在`try`块...

    rethrow:重新抛出与模板渲染,编译或其他处理相关的错误,以获取报告

    var rethrow = require ( 'rethrow' ) ; 有关用法示例,请参见。 原料药 在上下文中将给定的err重新抛出给给定lineno filename中有问题的模板表达式。 参量 err {Error} :错误对象 filename {String} :模板的...

    Java程序设计:chapter10 异常处理.ppt

    如果`catch`块不能完全处理异常,可以选择重新抛出(rethrow)异常,这样上层的调用者可以处理。这可以通过`throw`关键字实现,也可以使用`throw e`来直接抛出捕获到的异常对象。 5. **异常对象的生成**: 当异常...

    java程序实例 事件处理

    **示例四:RethrowException.java** ```java public class RethrowException { public static void f() throws Exception { System.out.println("the original exception in f()"); throw new Exception("thrown...

    linux程序栈回溯

    通过捕获`std::current_exception`,然后使用`std::rethrow_exception`,可以重新触发异常并进行栈回溯。 在生产环境中,为了不影响服务,可以配置核心转储(core dump)。当程序崩溃时,系统会生成一个包含了程序...

    nodejs-mysql

    在IT领域,特别是Web开发与后端服务设计中,Node.js与MySQL的结合是一种常见的技术栈选择,尤其在Linux环境下,这种组合提供了高效、灵活的数据处理能力。以下将深入解析如何在Linux系统下利用Node.js连接并操作...

    异常机制分析

    #### 异常的重新抛出(`rethrow`) 异常的重新抛出是指在`catch`块中再次抛出异常的行为。这通常发生在两种情况下:一种是在当前`catch`块无法处理异常时,另一种是在处理过程中触发了新的异常。异常的重新抛出只能...

    Exception

    另一种是重新抛出异常(rethrow),这允许保留原始异常信息,同时添加新的上下文信息。最后,可以创建自定义异常类,当特定类型的错误发生时,抛出自定义异常,这样可以使代码更具可读性和可维护性。 异常处理还有...

Global site tag (gtag.js) - Google Analytics