gpt4 book ai didi

c++ - 正确终止程序。使用异常

转载 作者:IT老高 更新时间:2023-10-28 21:50:40 24 4
gpt4 key购买 nike

问题:

如果我只想显示错误消息并关闭(考虑到我可能深入程序),使用异常是否是终止程序的正确方法?或者我可以直接调用类似 exit(EXIT_FAILURE) 的东西吗?

我目前在做什么:

我正在开发一个游戏项目,并试图找出在出现需要执行此类操作的错误时终止程序的最佳方法。例如,在无法加载纹理的情况下,我会显示一条错误消息并终止程序。

我目前正在这样做,但有以下异常(exception):

int main()
{
Game game;
try
{
game.run();
}
catch (BadResolutionException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Resolution");
return 1;
}
catch (BadAssetException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Assets");
return 1;
}
catch (std::bad_alloc & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Memory");
return 1;
}
return 0;
}

除了 bad_alloc 之外的所有异常都是我自己定义的从 runtime_error 派生的异常。

我不需要任何手动资源清理,我正在使用 std::unique_ptr 进行任何动态分配。我只需要显示错误信息并关闭程序。

研究/异常(exception)的替代方案:

我查看了很多关于 SO 和其他地方的帖子,并看到其他人说什么,从不使用异常到使用异常,但你使用它们是错误的。我还查找了明确调用 exit() 之类的方法。

使用 exit() 听起来不错,但我读到它不会通过调用堆栈返回到 main 清理所有内容(如果我能再次找到它,我会发布链接)。此外,根据 http://www.cplusplus.com/reference/cstdlib/exit/如果多个线程处于事件状态,则不应使用此选项。我确实希望至少在短时间内创建第二个线程,并且该线程中可能会发生错误。

不使用异常(exception)在此处与游戏有关的一些回复中提到 https://gamedev.stackexchange.com/questions/103285/how-industy-games-handle-their-code-errors-and-exceptions

使用异常(exception)已在此处讨论:http://www.quora.com/Why-do-some-people-recommend-not-using-exception-handling-in-C++

我读过许多其他资料,但这些是我最近看过的。

个人结论:

由于我在处理错误和使用异常方面的经验有限,我不确定我是否走在正确的轨道上。我根据上面发布的代码选择了使用异常的途径。如果您同意我应该处理那些异常(exception)情况,我是否正确使用它?

最佳答案

让所有异常传播到main 通常被认为是一种很好的做法。这主要是因为您可以确定堆栈正确展开并且所有析构函数都被调用(参见 this answer)。我也认为以这种方式做事更有条理;你总是知道你的程序将在哪里终止(unless the program crashes)。它还有助于更一致的错误报告(在异常处理中经常被忽略的一点;如果您无法处理异常,则应确保您的用户确切知道原因)。如果你总是从这个基本布局开始

int main(int argc, const char **argv)
{
try {
// do stuff
return EXIT_SUCCESS;
} catch (...) {
std::cerr << "Error: unknown exception" << std::endl;
return EXIT_FAILURE;
}
}

那么你就不会出错了。您可以(并且应该)添加特定的 catch 语句以获得更好的错误报告。

多线程时的异常

使用标准库功能在 C++11 中异步执行代码有两种基本方法:std::asyncstd::thread

首先是简单的。 std::async 将返回一个 std::future ,它将捕获并存储给定函数中抛出的任何未捕获的异常。在 future 上调用 std::future::get 会导致任何异常传播到调用线程中。

auto fut = std::async(std::launch::async, [] () { throw std::runtime_error {"oh dear"}; });
fut.get(); // fine, throws exception

另一方面,如果 std::thread 对象中的异常未被捕获,则将调用 std::terminate:

try {
std::thread t {[] () { throw std::runtime_error {"oh dear"};}};
t.join();
} catch(...) {
// only get here if std::thread constructor throws
}

对此的一种解决方案是将 std::exception_ptr 传递给 std::thread 对象,它可以将异常传递给:

void foo(std::exception_ptr& eptr)
{
try {
throw std::runtime_error {"oh dear"};
} catch (...) {
eptr = std::current_exception();
}
}

void bar()
{
std::exception_ptr eptr {};

std::thread t {foo, std::ref(eptr)};

try {
// do stuff
} catch(...) {
t.join(); // t may also have thrown
throw;
}
t.join();

if (eptr) {
std::rethrow_exception(eptr);
}
}

虽然更好的方法是使用 std::package_task:

void foo()
{
throw std::runtime_error {"oh dear"};
}

void bar()
{
std::packaged_task<void()> task {foo};
auto fut = task.get_future();

std::thread t {std::move(task)};
t.join();

auto result = fut.get(); // throws here
}

但除非你有充分的理由使用 std::thread,否则更喜欢 std::async

关于c++ - 正确终止程序。使用异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32257840/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com