0

我的代码:

#include "xception.h"
#include <iostream>
#include <stdio.h>
#include <signal.h>
#include <stdio.h>
#include <signal.h>
#include <execinfo.h>

void bt_sighandler(int sig, struct sigcontext ctx) 
{

    void *trace[16];
    char **messages = (char **)NULL;
    int i, trace_size = 0;

    trace_size = backtrace(trace, 16);
    /* overwrite sigaction with caller's address */
    trace[1] = (void *)ctx.eip;
    messages = backtrace_symbols(trace, trace_size);
    /* skip first stack frame (points here) */
    printf("[bt] Execution path:\n");
    for (i=1; i<trace_size; ++i)
    {
        printf("[bt] #%d %s\n", i, messages[i]);

        char syscom[256];
        sprintf(syscom,"addr2line %p -e sighandler", trace[i]); 
        system(syscom);
    }
}


void xception::initialize_xception()
{
    /* Install our signal handler */
    struct sigaction sa;

    sa.sa_handler = (void *)bt_sighandler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;

    sigaction(SIGUSR1, &sa, NULL);
}

这给了我错误:r@r-HP-Mini-110:~/l33t/freeln/Xception/source$ g++ -std=c++11 -g -rdynamic -Wall -o xcep_app application.cpp xception.cpp xception.cpp: In static member function ‘static void xception::initialize_xception()’: xception.cpp:38:28: error: invalid conversion from ‘void*’ to ‘__sighandler_t {aka void (*)(int)}’ [-fpermissive]

奇怪的是,之前编译的相同的东西放置时如下:

#include <stdio.h>
#include <signal.h>
#include <stdio.h>
#include <signal.h>
#include <execinfo.h>

void bt_sighandler(int sig, struct sigcontext ctx) 
{

  void *trace[16];
  char **messages = (char **)NULL;
  int i, trace_size = 0;

  trace_size = backtrace(trace, 16);
  /* overwrite sigaction with caller's address */
  trace[1] = (void *)ctx.eip;
  messages = backtrace_symbols(trace, trace_size);
  /* skip first stack frame (points here) */
  printf("[bt] Execution path:\n");
  for (i=1; i<trace_size; ++i)
  {
      printf("[bt] #%d %s\n", i, messages[i]);

      char syscom[256];
      sprintf(syscom,"addr2line %p -e sighandler", trace[i]); //last parameter is the name of this app
      system(syscom);
  }

}


int func_a(int a, char b) {

  char *p = (char *)0xdeadbeef;

  //a = a + b;
  //*p = 10;  /* CRASH here!! */
  a =9;

  return 2*a;
}


int func_b() {

  int res, a = 5;

  res = 5 + func_a(a, 't');

  raise(SIGUSR1);

  return res;
}


int main() {

  /* Install our signal handler */
  struct sigaction sa;

  sa.sa_handler = (void *)bt_sighandler;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_RESTART;

  //sigaction(SIGSEGV, &sa, NULL);
  sigaction(SIGUSR1, &sa, NULL);
  /* ... add any other signal here */

  /* Do something */
  printf("%d\n", func_b());

  printf("%s\n", "not dead yet :)");
}

你能指出我的错误吗?

4

3 回答 3

5

不管你怎么切,你都不能用

void bt_sighandler(int sig, struct sigcontext ctx)

void (int)需要回调的函数。您可能会通过使用强制类型转换成功地抑制错误消息,这将使代码正式“编译”,但这不会使您的程序在“工作”一词的任何有意义的意义上工作。

回调函数sa.sa_handler必须是void (int)函数,句点。没有办法解决它。如果您想将一些额外的外部数据“走私”到该函数中,则必须发明一种替代解决方案。您不能只是向回调函数添加任意参数,并期望调用者会以某种方式神奇地为您添加的参数提供适当的参数。

于 2013-06-05T18:12:32.490 回答
1

sa_handler成员struct sigaction是类型的函数指针void(*) (int)。相反,表达式的类型(void *)ctx.eipvoid *由于转换。void *在 C++ 中,不会发生从另一个指针类型的隐式转换,因此会出现错误。

于 2013-06-05T18:08:31.127 回答
1

不同之处在于,在C中,您可以将 a 隐式转换void *为任何其他指针类型,而在C++中则不能。

C++中,您需要对实际函数类型 ( void (*)(int)) 进行显式强制转换,以使其不会出错。

请注意,在CC++中,将 a 转换为函数指针是未定义的行为,但如果首先从兼容的函数指针转换,void *通常会起作用。void *此外,只有在所有参数类型完全相同的情况下,才能保证函数指针完全兼容,尽管您通常可以获得看起来与不同参数类型一起工作的东西(再次未定义的行为)。

于 2013-06-05T18:13:44.850 回答