打印分段故障原因

Lio*_*ior 11 c unix linux segmentation-fault

假设我有一个导致分段错误的代码.

char * ptr = NULL;
*ptr = "hello"; /* this will cause a segmentation fault */
Run Code Online (Sandbox Code Playgroud)

如何在运行时打印,内存中发生分段错误的地址,以及分段错误的原因(访问禁止的内存区域或其他内容).

我读到了关于核心转储文件,但我不确定它是否是正确的解决方案.

我怎样才能做到这一点?

PS,我知道我可以通过使用gdb或其他调试器实现这一点,但目的是通过使用代码和仅代码来实现.

Fat*_*ror 5

如果您想知道原因,您可以注册一个信号处理程序,例如:

void handler(int signum, siginfo_t *info, void *context)
{
  struct sigaction action = {
    .sa_handler = SIG_DFL,
    .sa_sigaction = NULL,
    .sa_mask = 0,
    .sa_flags = 0,
    .sa_restorer = NULL
  };

  fprintf(stderr, "Fault address: %p\n", info->si_addr);
  switch (info->si_code) {
  case SEGV_MAPERR:
    fprintf(stderr, "Address not mapped.\n");
    break;

  case SEGV_ACCERR:
    fprintf(stderr, "Access to this address is not allowed.\n");
    break;

  default:
    fprintf(stderr, "Unknown reason.\n");
    break;
  }

  /* unregister and let the default action occur */
  sigaction(SIGSEGV, &action, NULL);
}
Run Code Online (Sandbox Code Playgroud)

然后你需要在某个地方注册它:

  struct sigaction action = {
    .sa_handler = NULL,
    .sa_sigaction = handler,
    .sa_mask = 0,
    .sa_flags = SA_SIGINFO,
    .sa_restorer = NULL
  };


  if (sigaction(SIGSEGV, &action, NULL) < 0) {
    perror("sigaction");
  }
Run Code Online (Sandbox Code Playgroud)

基本上,您注册一个在 SIGSEGV 交付时触发的信号,并获得一些附加信息,以引用手册页:

   The following values can be placed in si_code for a SIGSEGV signal:

       SEGV_MAPERR    address not mapped to object

       SEGV_ACCERR    invalid permissions for mapped object
Run Code Online (Sandbox Code Playgroud)

这些映射到出现段错误的两个基本原因——您访问的页面根本没有被映射,或者您不被允许执行您尝试对该页面执行的任何操作。

在信号处理程序触发后,它会自行取消注册并替换默认操作。这会导致再次执行失败的操作,因此它可以被正常路由捕获。这是页面错误(获取段错误的前兆)的正常行为,因此诸如需求分页之类的事情会起作用。