为什么我在使用信号处理程序的代码中会出现分段错误?
Why do I get a segmentation fault in this code with a signal handler?
我在我的程序中编写了一个信号处理程序,但是在这个文件结构中我遇到了一个分段错误。但如果一切都在一个文件中,那么一切都可以正常工作。据我了解,它无法访问 return 地址。我该如何解决?
"test.h"
#ifndef TEST_H
#define TEST_H
#include <string.h>
#include <setjmp.h>
#include <signal.h>
static jmp_buf g_env;
void sig_handler(int sig);
endif TEST_H
"test.c"
#include "test.h"
void sig_handler(int sig) {
psignal(sig, "Signal");
siglongjmp(g_env, 1);
}
"main.c"
#include "test.h"
int main(void) {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGSEGV);
sigaction(SIGSEGV, &act, 0);
if (!sigsetjmp(g_env, 1)) {
raise(SIGSEGV);
}
return (1);
}
"Result:"
Signal: Segmentation fault
Segmentation fault (core dumped)
"Valgrind:"
==44698== Command: ./a.out
==44698==
Signal: Segmentation fault
==44698== Warning: client switching stacks? SP change: 0x1ffeffee08 --> 0xf7c1f413060a2966
==44698== to suppress, use: --max-stackframe=593925450715481250 or greater
==44698== Jump to the invalid address stated on the next line
==44698== at 0xF7C1F413060A2966: ???
==44698== Address 0xf7c1f413060a2966 is not stack'd, malloc'd or (recently) free'd
==44698==
==44698==
==44698== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==44698== Bad permissions for mapped region at address 0xF7C1F413060A2966
==44698== at 0xF7C1F413060A2966: ???
==44698== Invalid write of size 8
==44698== at 0x482F120: _vgnU_freeres (vg_preloaded.c:59)
==44698== Address 0xf7c1f413060a295e is not stack'd, malloc'd or (recently) free'd
==44698==
==44698==
==44698== Process terminating with default action of signal 11 (SIGSEGV)
==44698== General Protection Fault
==44698== at 0x482F120: _vgnU_freeres (vg_preloaded.c:59)
这是因为您有不同的 g_env
实例 - 每个翻译单元都有不同的 g_env
。因此,sigsetjmp
中使用的 g_env
缓冲区与 siglongjmp
中使用的缓冲区不同。
只需从以下位置删除 static
:
static jmp_buf g_env;
现在,只有一个 g_env
的全局实例。
我在我的程序中编写了一个信号处理程序,但是在这个文件结构中我遇到了一个分段错误。但如果一切都在一个文件中,那么一切都可以正常工作。据我了解,它无法访问 return 地址。我该如何解决?
"test.h"
#ifndef TEST_H
#define TEST_H
#include <string.h>
#include <setjmp.h>
#include <signal.h>
static jmp_buf g_env;
void sig_handler(int sig);
endif TEST_H
"test.c"
#include "test.h"
void sig_handler(int sig) {
psignal(sig, "Signal");
siglongjmp(g_env, 1);
}
"main.c"
#include "test.h"
int main(void) {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGSEGV);
sigaction(SIGSEGV, &act, 0);
if (!sigsetjmp(g_env, 1)) {
raise(SIGSEGV);
}
return (1);
}
"Result:"
Signal: Segmentation fault
Segmentation fault (core dumped)
"Valgrind:"
==44698== Command: ./a.out
==44698==
Signal: Segmentation fault
==44698== Warning: client switching stacks? SP change: 0x1ffeffee08 --> 0xf7c1f413060a2966
==44698== to suppress, use: --max-stackframe=593925450715481250 or greater
==44698== Jump to the invalid address stated on the next line
==44698== at 0xF7C1F413060A2966: ???
==44698== Address 0xf7c1f413060a2966 is not stack'd, malloc'd or (recently) free'd
==44698==
==44698==
==44698== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==44698== Bad permissions for mapped region at address 0xF7C1F413060A2966
==44698== at 0xF7C1F413060A2966: ???
==44698== Invalid write of size 8
==44698== at 0x482F120: _vgnU_freeres (vg_preloaded.c:59)
==44698== Address 0xf7c1f413060a295e is not stack'd, malloc'd or (recently) free'd
==44698==
==44698==
==44698== Process terminating with default action of signal 11 (SIGSEGV)
==44698== General Protection Fault
==44698== at 0x482F120: _vgnU_freeres (vg_preloaded.c:59)
这是因为您有不同的 g_env
实例 - 每个翻译单元都有不同的 g_env
。因此,sigsetjmp
中使用的 g_env
缓冲区与 siglongjmp
中使用的缓冲区不同。
只需从以下位置删除 static
:
static jmp_buf g_env;
现在,只有一个 g_env
的全局实例。