如果我自己生成异常,我可以在异常中包含任何信息:源文件的许多代码行和名称.像这样的东西:
throw std::exception("myFile.cpp:255");
Run Code Online (Sandbox Code Playgroud)
但是未处理的异常或不是由我生成的异常是什么?
我一直在读,我不应该抛出std::string一些或其他类来分配内存.像这里或更重要的是这里的第3点- 不要嵌入std::string对象.
所以现在我正在尝试将boost :: exception插入到我的项目中,我看到了什么:很多字符串.
为什么不提升符合自己的建议?
如果我有不能硬编码的参数,比如在配置文件中安装,我怎样才能将它们放入异常中而不使用std::string?
或者指南是否std::string仅使用std::string尽可能少的指南?我有点困惑......
我做了一些研究.如果我错了,请纠正我.
如果我理解正确,那就是关于抛出期间的分配以及分配的内存发生了什么.因此,如果我在构造函数中分配内存并且无法在异常的析构函数中释放内存,则内存会丢失,这将产生内存泄漏.但是在投掷之前分配它是可以的,所以异常是干净的.
我试过这个:
struct xexception {
int *ttt[10];
xexception() {
ttt[0] = new int[0xfffffffL];
ttt[1] = new int[0xfffffffL];
ttt[2] = new int[0xfffffffL];
ttt[3] = new int[0xfffffffL];
ttt[4] = new int[0xfffffffL];
ttt[5] = new int[0xfffffffL];
ttt[6] = new int[0xfffffffL];
ttt[7] = new int[0xfffffffL];
ttt[8] = new int[0xfffffffL];
ttt[9] = …Run Code Online (Sandbox Code Playgroud) 从析构函数抛出异常的主要问题是,在析构函数被调用的那一刻,另一个异常可能是"在飞行中"(std::uncaught_exception() == true),因此在这种情况下做什么并不明显.用新的"覆盖"旧的异常将是处理这种情况的可能方法之一.但是决定在这种情况下必须调用std::terminate(或其他std::terminate_handler).
C++ 11通过std::nested_exception类引入了嵌套异常功能.该特征可用于解决上述问题.旧(未捕获)异常可能只是嵌套到新异常中(反之亦然?)然后可能抛出嵌套异常.但是没有使用这个想法.std::terminate在C++ 11和C++ 14中仍然会出现这种情况.
所以问题.是否考虑过嵌套异常的想法?它有什么问题吗?是不是在C++ 17中会改变这种情况?
可能重复:
使C++程序崩溃的最简单方法是什么?
我在代码库中经常看到一个构造,程序以某种方式进入无效状态,代码会故意做错,只是为了强制崩溃.它通常是这样的:
if(<something is wrong>)
{
int *ptr = NULL;
*ptr = 0;
}
Run Code Online (Sandbox Code Playgroud)
这当然会导致空引用异常并以不可恢复的方式崩溃程序.我只是想知道这是否真的是最好的方法呢?首先,它读得不好.如果没有评论,您可能没有意识到此处发生的崩溃是有意的.其次,几乎没有办法从中恢复.它不会抛出异常,因此其他代码无法处理它.它只会使程序死亡,无法回溯.它也没有提供很多线索,说明为什么它必须在这里崩溃.它会在所有版本中崩溃,不像断言.(我们确实有一个非常强大的断言系统,但在这种情况下并不总是这样.)
这是我们在整个地方使用的风格,我无法试图说服任何人.我只是好奇这个行业有多常见.
编辑:关于为什么此问题中的代码有效的问题已通过重复标记中的链接问题得到解答.关于字符串文字生命周期的问题在这个问题的答案中得到了回答.
我试图了解如何以及何时const char *取消分配指向的字符串.
考虑:
const char **p = nullptr;
{
const char *t = "test";
p = &t;
}
cout << *p;
Run Code Online (Sandbox Code Playgroud)
离开内部范围后,我希望p是一个悬垂的指针const char *.但是在我的测试中并非如此.这意味着t即使在t超出范围之后,实际值仍然有效且可访问.
这可能是由于通过将它绑定到const引用来延长临时的生命周期.但我不做这样的事情,甚至通过t在成员变量中保存引用并从以后打印不同函数的值仍然给我正确的值.
class CStringTest
{
public:
void test1()
{
const char *t = "test";
m_P = &t;
test2();
}
void test2()
{
cout << *m_P;
}
private:
const char **m_P = nullptr;
};
Run Code Online (Sandbox Code Playgroud)
那么t这里价值的生命周期是多少?我会说我通过取消引用指向超出范围的变量值的指针来调用未定义的行为.但它每次都有效,所以我认为情况并非如此.
尝试其他类型的时候QString:
QString *p = …Run Code Online (Sandbox Code Playgroud) 我尝试在C++中创建的每个类都会发生这种情况.从java迁移,我发现问题主要在于创建类.我运行valgrind并且它在构造函数中,它似乎是.
==30214== Memcheck, a memory error detector
==30214== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==30214== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==30214== Command: ./CoC
==30214==
==30214==
==30214== Process terminating with default action of signal 11 (SIGSEGV)
==30214== Bad permissions for mapped region at address 0x404B4F
==30214== at 0x4C2B9EC: strcat (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30214== by 0x404220: Model::Model(std::string) (in /home/kronus/Apollo/CoC)
==30214== by 0x402617: main (in /home/kronus/Apollo/CoC)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我正在尝试将此模型类的构造函数调用到main方法中.这是构造函数的代码
Model::Model(std::string filename)
{
m_TotalFaces = …Run Code Online (Sandbox Code Playgroud) 所以我有一个有两个例外的程序。在这两种情况下,我都想抛出一个可以在主函数中捕获并在错误消息中使用的字符串。然而,据我所知
try {
...
} catch(string msg) {
cerr << "..." << msg << "..." << endl;
} catch (string msg2) {
cerr << "..." << msg2 << "..." << endl;
}
Run Code Online (Sandbox Code Playgroud)
不允许。有什么办法可以做到以上或类似的事情吗?谢谢