Pergunta

Como faço para obter um aplicativo C ++, incluindo uma biblioteca compartilhada da ADA carregada para gerar um dump do núcleo Ao travar?

Eu tenho um aplicativo C ++ que carrega uma biblioteca compartilhada da ADA, dentro do código da ADA, recebo um erro de estouro de pilha que causa a terminação do programa junto com a saída do console:

raised STORAGE ERROR

Nenhum arquivo de despejo principal é gerado até que eu emiti um "Ulimit -C Unlimited" antes de iniciar o aplicativo.

A mesma coisa acontece se eu enviar uma morte Sigsegv para o aplicativo.

Enviando matar Sigsegv Para outro aplicativo que não usa o ADA DLL, gera um arquivo de despejo principal da maneira que eu quero.

Encontrei algumas informações aqui: http://objectmix.com/ada/301203-gnat-fstack-check-does-work.html

ATUALIZADA! Como mencionado por Adrien, não há contradição, -s define o limite de pilha enquanto -C Define o limite do arquivo principal.

Ainda assim, o problema permanece. Eu verifiquei as bandeiras ao construir a biblioteca ADA e o Fstack-check A bandeira não foi definida, por isso deve gerar um dump do núcleo.

Embora eu ainda não tentei, parece um pouco estranho. Ele menciona a opção de compilador -fstack -check + definindo a variável GNAT_STACK_LIMIT, mas ao mesmo tempo se refere ao comando ulimit que parece uma contradição, definir "ulimit -c" é a única maneira que eu conheço de obter um dump do núcleo a ser gerado No momento do acidente, se isso ingerir com a opção de verificação do FSTack, então temos uma captura 22.

Foi útil?

Solução

Agora, quase 2 anos depois (ainda trabalhando na mesma empresa que Kristofer que fez quando fez a pergunta), foi a pergunta levantada novamente - e finalmente acho que entendo por que nenhum dump do núcleo é gerado !!

O problema é causado pelo tempo de execução da ADA, que, por padrão, implementa um manipulador de sinal para alguns signos do POSIX (para Linux: Sigabrt, Sigfpe, Sigill, Sigsegv e Sigbus). Para Gnat/Linux, o manipulador de sinal é chamado __gnat_error_handler dentro a-init.c, que se parece com o seguinte:

static void
__gnat_error_handler (int sig)
{
  struct Exception_Data *exception;
  char *msg;
  static int recurse = 0;
  ...
  switch (sig)
    {
    case SIGSEGV:

      if (recurse)
      {
        exception = &constraint_error;
        msg = "SIGSEGV";
      }
      else
      {
        ...
        msg = "stack overflow (or erroneous memory access)";
        exception = &storage_error;
      }
      break;
     }
    recurse = 0;
    Raise_From_Signal_Handler (exception, msg);
 }

Este manipulador é "em largura do processo" e será chamado por qualquer sinal acionado, independentemente de qual parte do processo se origina (independentemente da codificação em ADA/C/C ++ ...).

Quando chamado, o manipulador levanta uma exceção da ADA e o deixa no tempo de execução da ADA para encontrar um manipulador de exceção apropriado-se nenhum manipulador for encontrado (por exemplo, quando um SigseGV é gerado por qualquer parte do código C ++), o ADA -Runtime volta a encerrar o processo e apenas deixar uma impressão simples de __gnat_error_handler (por exemplo. "Stack Overflow (ou acesso errôneo na memória)").

http://www2.adacore.com/gap-static/gnat_book/html/node25.htm

Para impedir que Ada-Runtime lida com um sinal de Posix e converta-o em uma exceção da ADA, é possível desativar o beahviour padrão usando

PRAGMA INTERRUP_STATE (NOME => VALOR, ESTADO => SYSTEM | RUNDOME | Usuário);,

por exemplo. Para desativar o manuseio do Sigsegv, defina

Pragma Interrupt_State(SIGSEGV, SYSTEM);

No seu código ADA-agora o comportamento padrão do sistema será acionado quando um sigsegv for aumentado, e será gerado um despejo de núcleo que permite rastrear a origem do problema!

Eu acho que essa é uma questão muito importante a ser ciente ao misturar ADA e C/C ++ em *nix-plataforms, pois pode induzi-lo a pensar que os problemas são origens do código ADA (já que a impressão indica uma exceção gerada a partir de ADA ) Quando a fonte real do problema está no código C/C ++-...

Embora seja provavelmente seguro desativar o manuseio padrão da ADA-Runtime do Sigsegv (acho que nenhum programador sensato usando isso em qualquer manuseio de erros "esperado" ... bem, talvez usado no software de aviação ou similar, quando algum tipo de "último recurso "É preciso ter uma história funcional para evitar que algo muito ruim aconteça.) Acho que um pouco de cautela deve ser tomado e, em seguida," substituir "o manuseio da ADA-Runtime para sinais.

Uma questão pode ser o Sigfpe-Signal, que também levanta uma exceção ADA restant_error por padrão. Esse tipo de exceção pode ser usado pelo código ADA como um "comportamento excitado". Desativar o SIGFPE por Pragma interrupt_state pode afetar seriamente a execução do código ADA e travar sua aplicação durante "circunstâncias normais"-, por outro lado e deixe você sem nenhum traço real da origem do problema ...

Outras dicas

Isso me parece um verdade bom uso para o seu Adacore Apoio, suporte. Você não é responsável por encontrar muitas pessoas fora dessa empresa que estão familiarizadas com as implicações das interações entre o tempo de execução da GNU Ada e o C ++.

Eu sugeriria para depurar o código da ADA que você tenta colocar em um manipulador de exceção de última hora em tudo, o que, por sua vez, despeja a pilha de exceções. A maioria dos fornecedores tem alguma maneira de fazer isso, geralmente baseado em Ada.Exceptions.Exception_information e Ada.Exceptions.Exception_Message.

eu encontrei uma discussão do ponto de vista da segurança (encontrando malware). Basicamente, existem 10 sinais que você pode tentar, SIGSEGV é apenas um deles.

Parece que você pode simplesmente ligar sigaction(SIGSEGV, 0, SIG_DFL); para restaurar o comportamento do sinal padrão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top