我正在编写一个供内部使用的C共享库(如果这很重要,我将dlopen()用于c ++应用程序)。共享库通过JNI模块加载(除此之外)一些Java代码,这意味着所有恶梦错误模式的方式都可以来自我需要在应用程序中智能处理的JVM。此外,该库需要重入。在这种情况下是否存在用于传递错误字符串的习惯用法,或者我是否将映射错误粘贴到整数并使用printfs进行调试?
谢谢!
答案 0 :(得分:3)
我对问题的解决方法与其他人的方法略有不同。他们没有错,只是因为我不得不在这个问题的另一个方面进行斗争。
errno.h
代码表明错误的良好分类;实际上,如果您可以重用这些代码(或者只是传递它们,例如,如果您的所有错误最终来自系统调用),请执行此操作。
errno
本身。如果可能,直接从可能失败的函数返回错误代码。如果无法做到这一点,请在状态对象上使用GetLastError()
方法。你有一个状态对象,是吗?errno.h
代码不会删除它),请提供类似于strerror
的功能,将这些代码转换为人类可读的字符串。
errno
值的方法,名称涉及的文件(如果有的话),理想情况下也是系统调用本身的名称。人们经常会错误地看待这种错误 - 例如,SQLite,否则是一个设计良好的API,不会暴露errno
值或文件的名称,这使得难以区分“文件权限”数据库错误“来自”你的代码中有一个错误“。编辑:附录:该领域的常见错误包括:
另外,请仔细考虑应该允许哪些API失败。以下是一些永远不会失败的事情:
close
和munmap
不应该失败。值得庆幸的是,至少_exit
不能。)abort
失败,您应立即致电malloc
,而不是尝试将其传播给来电者。 (由于异常和RAII,在C ++中不是这样 - 如果你很幸运能够开发一个正确使用这两者的C ++项目。)结束时:有关如何处理所有错误的示例,请查看XPCOM。
答案 1 :(得分:2)
您返回指向static const char []
个对象的指针。这始终是处理错误字符串的正确方法。如果需要将它们本地化,则返回指向只读内存映射本地化字符串的指针。
答案 2 :(得分:1)
在C中,如果您没有国际化(I18N)或本地化(L10N)需要担心,那么指向常量数据的指针是提供错误消息字符串的好方法。但是,您经常发现错误消息需要一些支持信息(例如无法打开的文件的名称),这些信息实际上不能由常量数据处理。
考虑到I18N / L10N,我建议将每种语言的固定消息字符串存储在格式正确的文件中,然后在分叉任何线程之前使用mmap()
将文件“读取”到内存中。这样映射的区域应该被视为只读(在PROT_READ
的调用中使用mmap()
。)
这可以避免内存管理的复杂问题,并避免内存泄漏。
考虑是否提供可以调用以获取最新错误的函数。它可以有一个原型,如:
int get_error(int errnum, char *buffer, size_t buflen);
我假设其他函数调用返回错误号;库函数然后查询它有关当前线程的任何线程安全内存以及返回给该线程的最后一个错误条件,并将适当的错误消息(可能被截断)格式化为给定的缓冲区。
使用C ++,您可以从错误报告机制返回(引用)标准字符串;这意味着您可以格式化字符串以包含文件名或其他动态属性。收集信息的代码将负责释放字符串,由于C ++具有析构函数,因此不会(不应该)成为问题。您可能仍希望使用mmap()
来加载消息标记的格式字符串。
您需要注意加载的文件,特别是用作格式字符串的任何字符串。 (另外,如果您正在处理I18N / L10N,您需要担心是否使用'n$
表示法来允许参数重新排序;并且您必须担心不同文化/语言关于订单的不同规则其中出现一个句子的单词。)
答案 3 :(得分:0)
我想你可以像Windows一样使用PWideChars。它的线程安全。你需要的是调用应用程序创建一个PllChar,Dll将用它来设置错误。然后,callling app需要读取该PWideChar并释放其内存。
答案 4 :(得分:0)
R上。有一个很好的答案(使用静态const char []),但如果您将有各种口语,我喜欢使用Enum来定义错误代码。这比一些名称的#define更好于int值。
答案 5 :(得分:0)
errno
- 即使它可能被实现TLS);感谢Linux内核的return -ENOENT;
。strerror
的函数,它接受这样的整数并返回指向const字符串的指针。如果需要,此函数也可以透明地执行I18N,因为gettext-returnable字符串在翻译数据库的生命周期内也保持不变。答案 6 :(得分:0)
如果您需要提供非静态错误消息,那么我建议返回这样的字符串:error_code_t function(,char ** err_msg)。然后提供一个释放错误消息的函数:void free_error_message(char * err_msg)。这样,您可以隐藏错误字符串的分配和释放方式。这当然只值得实现您的错误字符串本质上是动态的,这意味着它们不仅仅传达错误代码的翻译。
请用mu格式来监督疏忽。我是用手机写的......