The Official GNOME 2 Developer's Guide GLib (五)
Yu
posted @ 2011年8月22日 15:19
in The Official GNOME 2 Developer's Guide GLib
with tags
c gnome gtk
, 2617 阅读
1.4.6 消息记录
为了在程序运行的时候能诊断错误,GLib在系统控制台提供了几个有用的小工具。下面是他们按照优先级来描述:(PS:优先级从低到高)
g_message() 表示程序在正常运行时候的行为提示。
g_warning() 不会导致程序错误的行为信息(至少调用它的时候没有错误)(PS:程序员只关系error不关心warning)
g_critical() 这个警告可能会导致错误。
g_error() 对于程序来说最严重的错误,调用它会立刻终止程序。
这些函数的参数和printf()的很像,都是一个格式化字符串和一个替代格式的参数列表。虽然你不必在每一个信息的最后都用换行符结束,但是为了确保你和你程序的用户知道这些信息是从你的程序发出的以区别其他程序,在编译的时候你就必须设置G_LOG_DOMAIN这个宏。用一个简单的字符串来定义你的应用软件或者是库。大部分的GNOME基本程序都是在编译选项的时候定义G_LOG_DOMAIN的。具体这样做: -DG_LOG_DOMAIN=\"名字\"。
下面这个程序演示了这四个函数:
/* messagedemo.c -- show logging features */ #include <glib.h> #define NR 42 int main(int argc, char **argv) { g_message("Coffee preparation engaged"); g_warning("Bean canister #%d empty", NR); g_critical("Water flow failure"); g_error("Heating element incinerated"); /* this program shouldn't reach this point */ return 0; }
(PS:这个输出是我改过的)
gcc `pkg-config --libs --cflags glib-2.0` -DG_LOG_DOMAIN=\"yu\" message.c -o message
这个程序的输出看来想这样:
yu-Message: Coffee preparation engaged
(process:3976): yu-WARNING **: Bean canister #42 empty
(process:3976): yu-CRITICAL **: Water flow failure
yu-ERROR **: Heating element incinerated
aborting...
Aborted
(PS:说明修改生效了)
为致命的错误标记错误等级
g_error()函数调用会在之前的程序中产生一个错误的信息。告诉你这个程序被终止了(也可能是core dump[1])。你还可以配置致命错误在其他日志里面的优先级是他们表现的一样。例如:
[code]
g_log_set_always_fatal(G_LOG_LEVEL_WARNING|G_LOG_LEVEL_CRITICAL)
[/code]
这个函数的参数是一个掩码,用来设置这些警告和严重消息的行为。你可以用下列常量按位进行或运算:
G_LOG_LEVEL_CRITICAL
G_LOG_LEVEL_WARNING
G_LOG_LEVEL_MESSAGE
G_LOG_LEVEL_INFO
G_LOG_LEVEL_DEBUG
注意:如果应用程序是用的GTK+或者是GNOME的库,你可以用命令行的选项 --g-fatal-warnings 来改变所有的警告等级。
自由消息
如果你有一条消息是不适合用预格式化的日志函数来输出,那你可以将它用g_print(), g_printerr()输出。g_print()输出到标准输出端(stdout),g_printerr()输出到标准错误端(stderr)。
注意:不同于日志消息函数(g_message())。函数g_print()和g_printerr()需要自己去指定消息中换行符的位置。
你可能会奇怪,为什么不用函数fprintf()来完成这个工作。不管你信不信(ps:反正我是信了),这个函数可能在Windows系统上无法正常工作。另外一个原因是英文,你可以定义自己的消息处理方式和可以改变的日志消息。并可以把他们输出到你想输出的任何地方(如一个窗口或者日志文件)。下面是一个例子:
/* printhandlerdemo.c */ #include <stdio.h> #include <glib.h> #define N 1 /* print messages in ALL CAPS */ void my_printerr_handler(gchar *string) { GString *msg; msg = g_string_new(string); msg = g_string_ascii_up(msg); fprintf(stderr, "%s\n", msg->str); g_string_free(msg, TRUE); } int main(int argc, char **argv) { /* print to stdout */ g_print("If you lie %d time, no one believes you.\n", N); /* print to stderr */ g_printerr("Ouch.\n"); /* but if you lie all of the time... */ g_set_printerr_handler((GPrintFunc)my_printerr_handler); g_printerr("%d. Ouch. Ouch. Ouch. (Hey, that really hurts.)", N); return 0; }
你可以在后面1.5.1的小节里面看到函数my_printerr_handler()是怎么工作的。下面是这个程序的输出:
If you lie 1 time, no one believes you.
Ouch.
1. OUCH. OUCH. OUCH. (HEY, THAT REALLY HURTS.)
正如你看到的那样,你可以用g_set_print_handler() 和 g_set_printerr_handler()这两个函数来设置你的打印函数。他们唯一的参数是一个GPrintFunc函数。定义如下:
typedef void (*GPrintFunc) (const gchar *string);
所以,你的回调函数必须定义为返回值是void而且仅有一个字符串参数的函数。
当你要构建自己的错误消息要用到两个或者两个以上的函数时候:g_sterror()和g_strsignal()。strerror()和strsignal()都是独立于平台的实现。g_strerror()函数接受一个如EBADF或EINVAL错误代码,并将其转换到一个更易于理解的消息“错误的文件描述符”或“无效的参数。”同样,g_strsignal()返回的一个信号的名称时,给出一个数字信号代码。
相对于strerror()和strsignal()来说它们的优势不是独立于不同平台,而是创造了一个UTF-8的输入输出库。例如:GTK+
[1]什么是Core Dump?
Core的意思是内存, Dump的意思是扔出来, 堆出来.开发和使用Unix程序时, 有时程序莫名其妙的down了, 却没有任何的提示(有时候会提示core dumped). 这时候可以查看一下有没有形如core.进程号的文件生成, 这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.