第10.6節中的示例代碼,預期的結果是:
經過多次迭代後,getpwnam使用的靜態結構將被破壞,並且程序將以SIGSEGV信號。即使在處理程序中重置,SIGALRM的信號處理程序也不起作用
但我的平臺的Fedora 11,GCC上(GCC)4.4.0,其結果是
[Langzi @自由APUE] $ ./corrupt
在sig_alarm
我只能看到sig_alarm
的輸出一次,程序似乎因爲某種原因掛起,但它確實存在,並且仍在運行。
但是,當我嘗試使用gdb來運行程序,似乎沒問題,我會定期看到從sig_alarm
的輸出。
從我的手冊中,它說信號處理程序將在信號處理後設置爲SIG_DEF,並且系統不會阻止信號。所以在我的信號處理程序開始時,我重置了信號處理程序。
也許我應該使用sigaction來代替,但我只想知道正常運行和gdb運行之間區別的原因。
任何意見和幫助將不勝感激。
下面是我的代碼:
#include "apue.h"
#include <pwd.h>
void sig_alarm(int signo);
int main()
{
struct passwd *pwdptr;
signal(SIGALRM, sig_alarm);
alarm(1);
for(;;) {
if ((pwdptr = getpwnam("Zhijin")) == NULL)
err_sys("getpwnam error");
if (strcmp("Zhijin", pwdptr->pw_name) != 0) {
printf("data corrupted, pw_name: %s\n", pwdptr->pw_name);
}
}
}
void sig_alarm(int signo)
{
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
err_sys("getpwnam error");
alarm(1);
}
感謝您的回覆。該示例的目的是爲了顯示我們是否從信號處理程序調用不可重入函數,結果是不可預測的。 Nonreentrant函數:a)使用靜態數據結構,b)調用malloc或free,c)使用標準I/O庫,因爲該庫以非新生方式使用全局數據結構。我們應該保存並恢復errno。 函數getpwnam使用靜態結構,因此在主循環中,調用可能會發現內部數據指針在信號處理程序調用相同函數時已損壞,並且程序將崩潰。 和 – OnTheEasiestWay 2009-11-01 11:09:19
並按照你的建議,呼叫警報是好的。但是該示例的預期結果不能顯示。這個例子是爲了演示關於信號處理器的錯誤方式,所以我只想知道它出錯的原因。再次感謝。 – OnTheEasiestWay 2009-11-01 11:20:22
是的,這個例子顯示你得到未定義的行爲。我假定其意圖是,字符串** pw_name **有時應該是錯誤的。但在我看來,它實際上已經顯示了更多,即未定義的行爲就是這樣,沒有定義,如果你期望它做一件特定的事情,它可能會做一些完全不同的事情。只是很高興它沒有融化電腦,或發送粗魯的電子郵件給你的母親! – 2009-11-02 10:00:34