[英]C - Higher Order Function
Signal 將回調函數作為其參數之一。 為了具有可變行為,我想在函數內創建一個函數。 到目前為止,這是我的嘗試:
typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
void sigintHandler(int sig) {
printf("Process %d", pid);
}
return sigintHandler
}
int main(void) {
...
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
...
}
...
}
但是,每次我發送 SIGTSTP (Ctrl-z) 時,都會出現段錯誤。
作為旁注:關於如何調試段錯誤的任何提示將不勝感激!
您的代碼可以編譯,因為它在語法上是正確的,並且您使用的是編譯器擴展; 但是,您的代碼存在一些基本問題,可能會導致您的segfault
。
首先,您的信號處理程序代碼:
typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
void sigintHandler(int sig) {
printf("Process %d", pid);
}
return sigintHandler;
}
這不是標准的 C 語言,甚至需要在某些版本的gcc
上指定-ftrampolines
標志才能實際編譯。
您的信號處理函數本身有一些需要解決的問題:
sigintHandler
是一個嵌套函數,因此當您的信號處理函數f
通過return sigintHandler;
,您正在返回一個函數指針。
在您的代碼中,這可以正確編譯,因為您有typedef void (*sighandler_t)(int);
,它定義了一個函數指針類型,該類型可以指向具有void
返回類型並以int
作為參數的函數,您的sigintHandler
定義為。
相反,您的信號處理函數可以簡單地編寫為:
void sigintHandler(int sig) {
printf("Signal %d\n", sig);
}
在您的主要功能中,您有以下內容:
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
// ....
}
這里應該注意這也有一些問題。 首先, signal
函數將信號編號(通常是在signal.h
頭文件中定義的宏)作為它的第一個參數,並將其作為第二個參數,一個指向定義為void func_name(int sig)
的函數的指針。
為此,您正在調用該函數而不是將其作為指針傳遞。
*f(1)
實際上調用f
並傳遞1
作為其參數; 相反,您可以將其更改為以下內容:
if (signal(SIGTSTP, f) == SIG_ERR) {
// ....
}
但這應該會發出警告/錯誤,因為f
被定義為返回函數指針而不是void
。
因此,要將代碼更改為合規,您只需執行以下操作:
#include <stdio.h>
#include <signal.h>
void sigintHandler(int sig) {
printf("Signal %d", sig);
}
int main(void) {
// ...
if (signal(SIGTSTP, sigintHandler) == SIG_ERR) {
// ...
}
// ...
return 0;
}
然而你說:
要有可變的行為......
這取決於您想要什么樣的變量性質,但如果它是基於信號的變量函數,您可以執行以下操作:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sig_stop(int sig) {
printf("Process %d stop\n", getpid());
}
void sig_int(int sig) {
printf("Process %d interrupt\n", getpid());
}
int main(void) {
// ...
if (signal(SIGTSTP, sig_stop) == SIG_ERR) {
// ...
}
if (signal(SIGINT, sig_int) == SIG_ERR) {
// ...
}
// ...
return 0;
}
或者你可以使用switch
語句:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sigHandler(int sig) {
printf("Process %d received %d\n", getpid(), sig);
switch (sig) {
case SIGTSTP:
// do stop code
break;
case SIGINT:
// do interupt code
break;
}
}
int main(void) {
// ...
if (signal(SIGTSTP, sigHandler) == SIG_ERR) {
// ...
}
if (signal(SIGINT, sigHandler) == SIG_ERR) {
// ...
}
// ...
return 0;
}
任何有關如何調試段錯誤的提示將不勝感激!
首先,了解什么是分段錯誤; 那么你可以使用像一個調試器gdb
通過您的代碼步驟或檢查故障轉儲,看看那里特別是segfault
的發生。
希望能有所幫助。
不確定您在問什么,但我可以幫助您了解您的分段錯誤。
當你調用一個函數時,有幾件事情要做。
當 1,2, 6 由 Calling 作用域完成時。
如您所知,signal 是一個void arguments
因此調用 (1) 會將0
參數壓入堆棧。
而 return (6) 將從堆棧中彈出您的“不存在的” int
並破壞它。
有點解決
你不能有帶參數的信號函數,
你能做的是:
您可以在信號函數中讀取全局變量。 因此讀取程序的當前狀態。
您可以通過 sys_call 獲取您的 process_id、thread_id。
我不推薦,但您可以將堆棧進一步讀取到先前的范圍並獲取它的局部變量。 使用 BIG 請注意,它不會是您將信號設置為...的功能,而是在發出信號時正在運行的功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.