关于:我想在我的 main 的小主体中,从我调用的函数中获取错误代码,以确定发生了什么,并将错误消息打印到 stderr 并使用相同的错误代码退出正如我得到的
第一个问题——人们会在 C 语言中这样做吗,这是一个好的目标吗?
就建筑而言,完全没有?
一些 人这样做,但所有人 人都应该这样做。它被认为是好的形式
秒问题是关于错误返回码和errno。我应该怎么
默认情况下在我的代码中使用?似乎这两个约定是
在 C 标准库中可以互换使用,这很令人困惑。
查看第一个答案。它很好地涵盖了这一点。 (+1 给@Sourav)
第三个问题是关于错误代码本身。在 C# 和 Java 中,有
是标准的异常类型,几乎涵盖了您想要的所有内容
除了特定的 cmets,通常会抛出。我应该使用 errno
为此目的的错误代码表,或者我应该创建一个单独的错误
我的应用程序的代码表,以包含它特定的所有内容
它?或者可能每个函数都应该维护它自己的特定表
错误代码?
这完全取决于开发者。创建应用程序时,我将使用生成条件的库调用所固有的特定错误代码/消息。当我创建一个 API(通常是 .dll)时,我通常会创建一个包含特定于应用程序的所有可能返回条件的单个枚举,并将 C 本机库错误也集成到这个枚举中。成功条件为零/正值,错误条件为负值。与此同时,我创建了一个与每个返回条件相对应的字符串描述数组。这些可由应用程序通过函数调用,例如。 int GetErrorDescription(int error, char *str);。但是,这可以通过几种不同的方式来处理,这只是我的方法。
示例:
/*------------------------------------------
//List of published error codes
/*-----------------------------------------*/
enum {
SUCCESS = 0,
COPYFILE_ERR_1 = -1, //"CopyFile() error. File not found or directory in path not found.",
COPYFILE_ERR_3 = -2, //"CopyFile() error. General I/O error occurred.",
COPYFILE_ERR_4 = -3, //"CopyFile() error. Insufficient memory to complete operation.",
COPYFILE_ERR_5 = -4, //"CopyFile() error. Invalid path or target and source are same.",
COPYFILE_ERR_6 = -5, //"CopyFile() error. Access denied.",
...
FOPEN_ERR_EIO = -11, //"fopen() error. I/O error.",
FOPEN_ERR_EBADF = -12, //"fopen() error. Bad file handle.",
FOPEN_ERR_ENOMEM = -13, //"fopen() error. Insufficient memory.",
...
GETFILESIZE_ERR_3 = -24, //"GetFileSize() error - Insufficient memory to complete operation.",
GETFILESIZE_ERR_4 = -25, //"GetFileSize() error - Invalid path or target and source are same.",
GETFILESIZE_ERR_5 = -26, //"GetFileSize() error - Access denied.",
...
PATH_MUST_BE_C_DRIVE = -38, //"SaveFile path variable must contain \"c:\\\".",
HEADER_FIELD_EMPTY = -39, //"one or more of the header fields are incorrect or empty.",
HEADER_FIELD_ILLEGAL_COMMA = -40, //"one or more of the header fields contains a comma.",
...
MAX_ERR = 46 // defines the size of the static char ErrMsg
};
和然后是一个函数来获取描述:
int API GetErrorMessage (int err, char * retStr)
{
//verify arguments are not NULL
if(retStr == NULL)
{
return UNINIT_POINTER_ARGUMENT;
}
switch(err) {
case COPYFILE_ERR_1 : strcpy(retStr, "CopyFile() error. File not found or directory in path not found." ); break;
case COPYFILE_ERR_3 : strcpy(retStr, "CopyFile() error. General I/O error occurred." ); break;
case COPYFILE_ERR_4 : strcpy(retStr, "CopyFile() error. Insufficient memory to complete operation." ); break;
case COPYFILE_ERR_5 : strcpy(retStr, "CopyFile() error. Invalid path or target and source are same." ); break;
case COPYFILE_ERR_6 : strcpy(retStr, "CopyFile() error. Access denied." ); break;
...
case FOPEN_ERR_EIO : strcpy(retStr, "fopen() error. I/O error." ); break;
case FOPEN_ERR_EBADF : strcpy(retStr, "fopen() error. Bad file handle." ); break;
case FOPEN_ERR_ENOMEM : strcpy(retStr, "fopen() error. Insufficient memory." ); break;
...
case GETFILESIZE_ERR_3 : strcpy(retStr, "GetFileSize() error - Insufficient memory to complete operation." ); break;
case GETFILESIZE_ERR_4 : strcpy(retStr, "GetFileSize() error - Invalid path or target and source are same." ); break;
case GETFILESIZE_ERR_5 : strcpy(retStr, "GetFileSize() error - Access denied." ); break;
...
case HEADER_FIELD_EMPTY : strcpy(retStr, " one or more of the header fields are incorrect or empty." ); break;
case HEADER_FIELD_ILLEGAL_COMMA : strcpy(retStr, " one or more of the header fields contains a comma." ); break;
case EVENT_FIELD_EMPTY : strcpy(retStr, " one or more of the event fields is incorrect or empty." ); break;
case EVENT_FIELD_ILLEGAL_COMMA : strcpy(retStr, " one or more of the event fields contains a comma." ); break;
...
default: strcpy(retStr, ""); break;
}
return 0;
}
最后,关于错误的附加信息:我在 C# 中发现,
至少,能够抛出异常是非常有用的
具有特定注释的预定义类型,该注释提供额外的
信息。在 C 错误管理中是否使用了类似的东西?如何
我应该实现它吗?
解决上一个问题的评论也解决了这个问题。
为什么库函数同时使用返回码和errno
而不是坚持一个或另一个?使用有什么好处
两者都有?
再次,由 Sourav 报道。