esta página:
- Descrição
- Exemplos de comum segfaults
- Encontrar fora dos limites da matriz de referências
- Verifique shell limites
- Use depuradores para diagnosticar segfaults
Descrição
Uma falha de segmentação (aka segfault) é uma condição comum que faz com que a falha de programas; eles são frequentemente associados com um arquivo chamado core
. Segfaults são causados por um programa tentando ler ou escrever um local de memória ilegal.
a memória de Programa é dividido em diferentes segmentos: um segmento de texto de instruções de programa, um segmento de dados para variáveis e matrizes definidas em tempo de compilação, um segmento de pilha temporária (ou automática) variáveis definidas no sub-rotinas e funções, e um segmento de pilha para as variáveis alocadas durante o tempo de execução por funções, tais como malloc
(C) e allocate
(Fortran). Para mais, Veja sobre os segmentos do programa.
uma segfault ocorre quando uma referência a uma variável cai fora do segmento onde essa variável reside, ou quando uma escrita é tentada para um local que está em um segmento apenas de leitura. Na prática, segfaults são quase sempre devido ao tentar ler ou escrever um inexistente elemento de matriz, não corretamente a definição de um ponteiro antes de usá-lo, ou (em programas C) acidentalmente, usando o valor de uma variável como um endereço (consulte o scanf
exemplo abaixo).
Exemplos de comum segfaults
- Por exemplo, chamar
memset()
como mostrado abaixo seria fazer com que um programa segfault:memset((char *)0x0, 1, 100);
- três casos A seguir ilustram os tipos mais comuns relacionadas com a matriz segfaults:
Caso /* "Array out of bounds" error valid indices for array foo are 0, 1, ... 999 */ int foo; for (int i = 0; i <= 1000 ; i++) foo = i;
Caso B /* Illegal memory access if value of n is not in the range 0, 1, ... 999 */ int n; int foo; for (int i = 0; i < n ; i++) foo = i;
C /* Illegal memory access because no memory is allocated for foo2 */ float *foo, *foo2; foo = (float*)malloc(1000); foo2 = 1.0;
- No caso A, matriz
foo
está definido paraindex = 0,1, 2, ... 999
. No entanto, na última iteração dofor
loop, o programa tenta acessarfoo
. Isto resultará em uma segfault se essa localização de memória estiver fora do segmento de memória ondefoo
reside. Mesmo que não cause uma segfault, ainda é um bug. - No caso B, inteiro
n
pode ser qualquer valor aleatório. Como no caso A, se não estiver na gama0, 1, ... 999
, pode causar uma segfault. Quer seja ou não, é certamente um bug. - No caso C, alocação de memória para variável
foo2
foi negligenciada, entãofoo2
irá apontar para uma localização Aleatória na memória. Acessandofoo2
provavelmente resultará em uma segfault.
- No caso A, matriz
- outro erro de programação comum que leva a segfaults é a supervisão no uso de ponteiros. Por exemplo, a função C
scanf()
espera o endereço de uma variável como o segundo parâmetro; portanto, o seguinte provavelmente fará com que o programa falha com um segfault:int foo = 0; scanf("%d", foo); /* Note missing & sign ; correct usage would have been &foo */
A variável
foo
pode ser definido na localização de memória1000
, mas acima de chamada de função iria tentar ler dados inteiro na memória local0
de acordo com a definição defoo
. - uma segfault ocorrerá quando UM programa tenta operar em um local de memória de uma forma que não é permitido (por exemplo, tentativas de escrever um local somente para leitura resultariam em uma segfault).
- Segfaults também podem ocorrer quando o seu programa fica sem espaço de pilha. Este pode não ser um bug no seu programa, mas pode ser devido ao seu shell definir o limite de tamanho da pilha muito pequeno.
encontre referências de array fora dos limites
a maioria dos compiladores Fortran tem uma opção que irá inserir código para fazer a verificação de limites em todas as referências de array durante a execução. Se um acesso cair fora do intervalo de índice definido para um array, o programa irá parar e dizer-lhe onde isso ocorre. Para a maioria dos compiladores Fortran, a opção é -C
, ou -check
seguido por uma palavra-chave. Veja o Guia de usuário do seu compilador para obter a opção exata. Use a verificação de limites apenas quando depurar, uma vez que irá atrasar o seu programa. Alguns compiladores C também têm uma opção de verificação de limites.
verifique os limites da linha de comandos
como indicado no último exemplo acima, alguns problemas de segfault não são devidos a erros no seu programa, mas são causados pelo facto de os limites de memória do sistema estarem muito baixos. Normalmente é o limite no tamanho da pilha que causa este tipo de problema. Para verificar os limites de memória, use o ulimit
comando bash
ou ksh
, ou limit
comando csh
ou tcsh
. Tente ajustar o stacksize mais alto, e em seguida, Executar novamente o seu programa para ver se a segfault vai embora.
Use depuradores para diagnosticar segfaults
Se você não conseguir encontrar o problema de outra forma, você pode tentar um depurador. Por exemplo, você pode usar o GNU é bem conhecido depurador GDB
para visualizar o backtrace de uma core
arquivo despejado por seu programa, sempre que programas segfault, eles costumam despejar o conteúdo (seção a) memória no momento da falha em um core
arquivo. Inicie o seu depurador com o comando gdb core
, e depois use o comando backtrace
para ver onde estava o programa quando ele estoirou. Este simples truque vai permitir que você se concentre nessa parte do Código.
If using backtrace
on the core
g file doesn’t find the problem, you might have to run the program under debugger control, and then step through the code one function, or one source code line, at a time. Para fazer isso, você precisará compilar seu código SEM otimização, e com a opção -g
, então informações sobre linhas de código fonte serão incorporadas no arquivo executável. Para mais, veja exemplo passo a passo para usar o GDB dentro do Emacs para depurar um programa em C orC++.