0

gcc (GCC) 4.7.2 c89

我一直想知道从被调用函数返回错误消息时的最佳实践是什么?

在我正在创建的一个共享库中,我有这个功能:

/* Create directory structure */
apr_status_t dir_create(apr_pool_t *mem_pool)
{
#define SRC "test_src"

    apr_fileperms_t file_perms =
        APR_FPROT_UWRITE   |
        APR_FPROT_GWRITE   |
        APR_FPROT_WWRITE   |
        APR_FPROT_UREAD    |
        APR_FPROT_GREAD    |
        APR_FPROT_WREAD    |
        APR_FPROT_UEXECUTE |
        APR_FPROT_GEXECUTE;

    if(apr_dir_make(SRC, file_perms, mem_pool) != APR_SUCCESS) {
        LOG_CRIT("Failed to create directory");
        return FALSE;
    }

    return TRUE;
}

LOG_CRIT显示与 errno 相关的相应错误消息。

在我将调用此函数的应用程序中,我有这个:

if(dir_create(mem_pool) != TRUE) {
    return 1;
}
LOG_INFO("Directory has been created");

例如,当上述失败时,它将像这样记录:

[CRITICAL] dir_create:28: error [File exists] Failed to create directory

我想知道我是否应该将错误消息放在调用库函数的应用程序中。或者您是否应该始终在最早收到错误消息时立即显示它?

在上述情况下,我在被调用函数中显示错误消息。当函数返回时,我只返回 1 以结束应用程序或执行其他操作。

另一个想法,最好返回错误指示器,让调用函数显示错误的来源?

4

2 回答 2

2

一些选项,变得越来越疯狂——你可能对什么适合你的情况有直觉;-P 这更多是为了激发你对选项的认识:

  • 尽可能多地捕获您认为合理的信息 - __FILE__, __LINE__, errno, 错误描述、正在尝试的操作、参数、结果等 - 在检测错误的线路上
  • 原则:只做调用者想让你做的事情;许多不同妥协的方法:
    • 返回一个小的、易于测试的数据值(数字或指针),但提供一些访问函数来轻松获取上面捕获的其他信息,以便您“返回”的代码可以做任何他们喜欢的事情......
      • 例如,调用者可以取消引用该指针以获取错误详细信息,strerror()类似函数,调用者给出一个指向可打印错误消息的指针(如果调用者不需要对该消息含义的可见性)......
    • 立即通知调用者控制的例程,该例程可以在调用者认为适当时抑制或重定向错误;例如,您的库可以提供指向您调用的函数的指针,调用者可以重定向该函数 - 默认值可以记录到标准错误或其他一些通常可接受的操作
    • 将您的库代码设计为#included 并使用调用者提供的预处理器宏来规定错误处理行为
    • 从您的库中硬编码错误消息的输出,但让调用者修改可能发送到的流,以便他们可以在需要时抑制它

如果使用您的库的应用程序可能想要推测性地尝试操作(例如故障转移或事务语义),特别是如果某些错误操作具有不可逆转的后果(例如某些批处理作业系统认为作业如果在 stderr 上打印任何内容,则失败 - 但从程序的角度来看,您的库函数可能不会构成失败,或者弹出图形错误对话框会阻碍无人值守操作)。

于 2013-04-23T08:33:19.143 回答
1

我建议您在尽可能低的级别记录错误消息,就像您在这里所做的那样。如果您需要访问errno,这一点尤其重要,否则在您获得更高级别的功能时可能会发生变化。在这个级别上,我会让错误消息尽可能的技术性和具体性。

根据您的库函数的返回值,您的应用程序代码可能会采取一些行动(例如,它可能会显示一个弹出窗口,提供人类可读的错误描述,或者它可能会写入stderr)。这通常会在可能的最高级别完成 - 如果您愿意,可以在 UI 级别。

于 2013-04-23T07:50:12.883 回答