草庐IT

c++ - 摆脱丑陋的 C 结构

coder 2024-02-15 原文

我继承了一段(大)代码,它有一个错误跟踪机制,他们将一个 bool 变量传递给他们调用的所有方法,并且在执行的各个阶段出现错误时,该方法被停止并返回,有时是默认值值(value)。

类似(之前):

#include <iostream.h>
int fun1(int par1, bool& psuccess)
{
    if(par1 == 42) return 43;
    psuccess = false;
    return -1;
}
int funtoo(int a, bool& psuccess)
{
    int t = fun1(a, psuccess);
    if(!psuccess)
    {
        return -1;
    }
    return 42;
}
void funthree(int b, bool& psuccess)
{
    int h = funtoo(b, psuccess);
    if(!psuccess)
    {
         return;
    }
    cout << "Yuppi" << b;
}
int main()
{
    bool success = true;
    funthree(43, success);
    if(!success)
    {
        cout<< "Life, universe and everything have no meaning";
    }
}

请注意,这是 C 和 C++ 代码的混合体,正是项目所在的位置。

现在,出现了一段 C 魔法:“某人”在某处定义了一个宏:

#define SUCCES_OR_RETURN  if(!psuccess) return

上面的程序变成了(AFTER):

#include<iostream.h>
int fun1(int par1, bool& psuccess)
{
    if(par1 == 42) return 43;
    psuccess = false;
    return -1;
}
int funtoo(int a, bool& psuccess)
{
    int t = fun1(a, psuccess);
    SUCCES_OR_RETURN -1;
    return 42;
}
void funthree(int b, bool& psuccess)
{
    int h = funtoo(b, psuccess);
    SUCCES_OR_RETURN ;
    std::cout << "Yuppi" << b;
}
int main()
{
    bool success = true;
    funthree(43, success);
    if(!success)
    {
        cout<< "Life, universe and everything have no meaning";
    }
}

问题:我想知道是否有更好的方法来处理这种错误跟踪,或者我不得不忍受这种情况。我个人不喜欢滥用 CSUCCES_OR_RETURN 即。一旦它被调用时带有参数,而在其他情况下它被调用时没有参数,感觉就像一个真正的 return 语句,但我没有找到任何更好的解决方案来解决这个古老的设计。

请注意,由于平台限制,我们有一些限制,但无论如何我都愿意听到关于这两个的意见:

  • 抛出异常。该代码是相互调用的 C 和 C++ 函数的混合体,编译器有点不支持 throw(在语法中接受但不对其执行任何操作,只是一个警告)。此解决方案是在 C++ 环境中解决此问题的标准方法。
  • C++11 特性,这是一个微型嵌入式平台,带有一个晦涩而古老的“几乎”C++ 编译器,该编译器不支持最新的 C++ 特性。但是,为了将来引用,我很好奇 C++11 是否提供了任何东西。
  • 模板魔法。编译器无法理解复杂的模板化问题,但我再次愿意看到您能提出的任何解决方案。

编辑

此外,正如@BlueMoon 在推荐中所建议的那样,创建一个全局变量是行不通的,因为在调用 success 变量的函数链的最开始是一个类的成员变量,并且有这个类创建了几个对象,每个对象都需要报告它的成功状态:)

最佳答案

此处对混合 C 和 C++ 错误处理策略进行了很好的 segmentation :

引用链接文章,您的选择主要归结为:

  • 从可能失败的函数中返回错误代码。
  • 提供类似于 Windows 的 GetLastError() 或 OpenGL 的 glGetError() 的函数来检索最近发生的错误代码。
  • 提供一个包含最新错误的全局(好吧,希望是线程本地的)变量,例如 POSIX 的 errno。
  • 提供一个函数来返回有关错误的更多信息,可能与上述方法之一结合使用,例如 POSIX 的 strerror 函数。
  • 允许客户端在发生错误时注册回调,例如 GLFW 的 glfwSetErrorCallback
  • 使用特定于操作系统的机制,例如结构化异常处理。
  • 将错误写入日志文件、stderr 或其他地方。
  • 发生错误时只需 assert() 或以其他方式终止程序。

您继承的代码的作者似乎选择了一种相当奇怪的方式,将指针传递给 bool 值 [sic] 以供函数使用似乎很不寻常。

这篇文章有一些很好的例子,我个人喜欢这种风格:

libfoo_widget_container_t container = NULL;
libfoo_error_details_t error = NULL;
if (libfoo_create_widgets(12, &container, &error) != libfoo_success) {
    printf("Error creating widgets: %s\n", libfoo_error_details_c_str(error));
    libfoo_error_details_free(error);
    abort(); // goodbye, cruel world!
}

在这里你得到了所有的东西,传入错误类型的指针,与成功常量(而不是 0|1)的比较,C 和世界其他地方之间的痛苦二分法! ).

我不认为说你的宏最好用 goto 来实现并不过分,无论如何,如果一个函数正在调用 SUCCES_OR_RETURN 不止一次,这可能是函数做得太多的线索。复杂的清理,或者 return 可能是代码的味道,你可以在这里阅读更多 http://eli.thegreenplace.net/2009/04/27/using-goto-for-error-handling-in-c/

关于c++ - 摆脱丑陋的 C 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23471187/

有关c++ - 摆脱丑陋的 C 结构的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby-on-rails - 一般建议和推荐的文件夹结构 - Sinatra - 2

    您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  8. ruby - 如何在 ruby​​ 中复制目录结构,不包括某些文件扩展名 - 2

    我想编写一个ruby​​脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"

  9. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐