Como evitar "Core dump"

PHP, Java, JavaScript, XML, XHTML, HTML, CSS, ASP, Delphi, Assembly, LaTeX, C, UML, Flash, Perl, SQL, Python, Zope, Pascal, WML. Se conhece mais de 3 siglas referidas, este é o forum para si.

Moderadores: Administradores, Moderadores

Como evitar "Core dump"

Mensagempor Sniper PT » Terça Fev 01, 2005 0:29

Olá a todos!

Iniciei a programar em C há pouco tempo, e muitos colegas meus (e eu inclusivé) quando estão a compilar têm erros do género "core dump"... estes erros são originados por mau manuseamento com a memória.... e é aqui que me surge uma dúvida:

Como é que hei-de proceder (no código) para evitar este tipos de erros?
Sniper PT
Membro de Prata
Membro de Prata
 
Mensagens: 414
Registado: Terça Jul 08, 2003 12:07

Mensagempor Andre_Oliveira » Terça Fev 01, 2005 3:25

Epa Core Dump e Segmentation Fault são os erros mais lixados para se tirar.

Digo isto porque cheguei a passar noites a tentar tirar um segmentation Fault de um trabalho de programação.

Muitas vezes esses erros são de apontadores a apontarem para zonas nulas em memória.
Imagem
Andre_Oliveira
Membro de Ouro
Membro de Ouro
 
Mensagens: 638
Registado: Terça Abr 20, 2004 4:09
Localização: Açores/LX

Mensagempor Tretabyte » Terça Fev 01, 2005 18:18

Boas,
como evitar um core dump? lol simples, nao des erros no codigo :P
tudo depende do codigo que estejas a trabalhar na altura, no log do debugger, de n coisas, um core dump pode ser facilmente resolvido ou nem por isso.

sem mais
Tretabyte
Avatar do Utilizador
Tretabyte
Gurus
Gurus
 
Mensagens: 5333
Registado: Sábado Jan 17, 2004 13:17
Localização: Lx

Re: Como evitar "Core dump"

Mensagempor ZePinga » Sábado Fev 05, 2005 16:21

Sniper PT Escreveu:Olá a todos!

Iniciei a programar em C há pouco tempo, e muitos colegas meus (e eu inclusivé) quando estão a compilar têm erros do género "core dump"... estes erros são originados por mau manuseamento com a memória.... e é aqui que me surge uma dúvida:

Como é que hei-de proceder (no código) para evitar este tipos de erros?



Boas,

Como sabes quando se programa nós ñ queremos ter erros, portanto qd aparecem não foi pq os quiseste lá meter :lol: . Bom quando tens erros do tipo segmention fault, bus error ... é de facto erros de memoria o core dump significa que quando executaste o programa o sistema criou um ficheiro core com informações sobre o erro enfim que não ajudam muito.

Esse tipo de erros adveem normalmente da mau manuseamento de ponteiros!. Ponteiros mal inicializados, alocações de memoria mal feitas que só podes detectar, correndo o gdb (no meu caso uso o DDD front-end para o gdb) , que é um debugger e vais ver onde é que o teu programa explode.

Tem em atenção aos mallocs e á quantidade de espaço que alocaste, incialização de ponteiros que o compilador não te avisa qd compilas, um erro comum é este:

int foo = 30;
char bar[foo];
bar = "eu auauauaua";


Repara que o bar não é mais que um vector de caracteres, em que bar aponta para a 1º posição do espaço de endereçamento desse vector. Teoricamente tas a pensar bom então sabendo que o char é 1 bytes alocou-se 30 bytes e tenho 30 posições para por em cada uma um caracter. O problema é que isso está completamente errado mas o compilador não se ira queixar, alias até pode aparecer a tua palavra mas já deves estar, quase de certeza a escrever por cima de memoria que não pertence a esse vector. Pelo simples facto que não podes inicializar um vector com uma varivel ou seja só podes alocar espaço dando-lhe uma constante eg. char bar[30] ou const int A = 30; bar[A]; ou ainda com macro #define A 30 ... bar[A]; . Se meteres como nesse exemplo uma variavel não estas a alocar esses 30 bytes, o que vai acontecer é que alocas um espaço que não tas á espera. Pode funcionar bem, o compilador não avisa e pode rebentar o teu programa 200 linhas a baixo dessa alocação , isso vê-se bem no DDD. Ficas à rasca à procura pq é q o raio do erro acontece naquela linha lol o problema é q o erro já foi 200 linhas atrás ;).

Welcome to C :lol:

Vais gostar de C mas tem cuidado com as alocações e smp que tenhas um segmention fault , suspeita dos malloc, realloc, inicialização de ponteiros , se não estas a apontar para uma string local que depois de sair da função se perde e ficas a apontar para NULL etc..

Ou uma maneira de teres menos erros é smp smp que utilizas ponteiros e por uma questão de debugging fazes o seguinte , imagina q queres usar um ponteiro qualquer....... :

if( BAR == NULL)
perror(" Ta null fdzz, já tou com problemas");

:D

Espero que tenha ajudado e boa sorte , ferramentas de trabalho gdb/DDD e valgrind ! Editor? Eclipse + cdt plugin em www.eclipse.org

cya :wink:
Editado pela última vez por ZePinga em Segunda Fev 07, 2005 1:02, num total de 2 vezes.
IST, Lisbon DEI - LEIC
www.dei.ist.utl.pt
ZePinga
Aprendiz
Aprendiz
 
Mensagens: 98
Registado: Domingo Set 12, 2004 22:29

Mensagempor jcorreia » Domingo Fev 06, 2005 2:06

Sniper, as Segmentation Faults são causadas por um acesso indevido à memória pelo programa, nomeadamente, este erro comum é causado por um acesso a uma posição de memória que se encontra fora do espaço de endereçamento destinado ao programa. Este acesso indevido é muitas vezes causado por uma manipulação errada de ponteiros ou indices de arrays. Considera o seguinte array de char's:

char string[] = "foobar";

Este array de caracteres terá como conteúdo 'f' 'o' 'o' 'b' 'a' 'r' '\0'. Um erro muito comum é, ao ler um array destes, formularmos uma condição de paragem incompleta o que poderá levar ao acesso a posições de memória que não estão disponíveis ao programa.

Utilizando a string acima, num ciclo que incrementa o indice i, até encontrar a primeira letra 'm', é um exemplo de como se pode violar o espaço de endereçamento do programa. Visto que a string utilizada não contém nenhuma letra 'm' este ciclo não para.

int i = 0;

while(string[i++] != 'm');

Visto que a string utilizada não contém nenhuma letra 'm' este ciclo não para - a não ser que ao percorrer as posições de memória seguintes encontre por acaso o valor 'm', o que é possível visto que a memória não é inicializada com nenhum valor - pois a condição de paragem será sempre verdadeira para a string dada e para as posições de memória seguintes.

Atenção que as SegFaults não acontecem por ultrapassar o índice do array mas sim por ultrapassar o espaço de endereçamento destinado ao programa. Imagina que o teu programa só pode utilizar a memória desde o endereço 1000 e 2000 - simplificando bastante as coisas, mas sem perdendo generalidade. Se tu começas a ler um array que começa no endereço 1300, posição a posição sem parar, quando chegares à posição 2001 o teu programa estará a violar o seu espaço de endereçamento, entrando numa zona de memória que poderá estar reservada a outro programa. Isto, sem entrar em detalhes, desencadeia esse erro: Segmentation Fault. Que depois origina um core dump.

Não ligues ao que o ZePinga te disse pois dali só saíram uma série de barbaridades. Fico abismado como um aluno do IST diz tanta coisa errada, ainda por cima para ajudar alguém que está somente a começar. O estrago que seria na vida do Sniper se eu não estivesse aqui... Enfim... ZePinga, talvez sejas do curso de Quimíca e como tal a tua falta de conhecimentos sobre a C seja compreensível - com o devido respeito a todos os Químicos que percebem bastante de programação.

Passo a enunciar alguns dos equívocos do ZePinga:

1. int foo = 30;
char bar[foo];

Esta sequência de instruções é perfeitamente válida e o que elas fazem é declarar-te um array de caracteres com 30 posições. *PODES* utilizar uma varíavel no tamanho do array a criar - o tamanho desse array será o valor da variável, neste caso 30, e não o endereço.

2. #define A 30 bar[A];

Se fizeres isto, quando usares A no teu código, todas as letras A serão substituidas por 30 bar[A]; e não irá definir um array com A posições. O que deves fazer é o seguinte:

#define A 30

char bar[A];

Edit: char string[10] = "foobar"; -> char string[] = "foobar";
As maneiras de inicialização de strings são basicamente as seguintes:
1. char string1[] = "Uma string declarada como um array\n";

2. char *string2 = "Uma string declarada como ponteiro\n";

3. char string3[30];
strcpy(string3, "Um constante de string copiada.\n");

Portanto, char string[10] = "String"; é inválido. Peço desculpa pelo equívoco.
Editado pela última vez por jcorreia em Segunda Fev 07, 2005 2:29, num total de 2 vezes.
jcorreia
Novato
Novato
 
Mensagens: 3
Registado: Sábado Fev 05, 2005 23:34

Mensagempor ZePinga » Domingo Fev 06, 2005 23:59

Se te estas a referir ao meu exemplo eu tinha espaçado para explicar que eram duas instruções , enfim compreendo que se interpretava mal por isso editei e meti ... .


xau xau
Editado pela última vez por ZePinga em Segunda Fev 07, 2005 18:54, num total de 1 vez.
IST, Lisbon DEI - LEIC
www.dei.ist.utl.pt
ZePinga
Aprendiz
Aprendiz
 
Mensagens: 98
Registado: Domingo Set 12, 2004 22:29

Mensagempor ZePinga » Segunda Fev 07, 2005 1:29

Passo a enunciar alguns dos equívocos do ZePinga:

1. int foo = 30;
char bar[foo];
bar = "foobar";

Esta sequência de instruções é perfeitamente válida e o que elas fazem é declarar-te um array de caracteres com 30 posições em que as posições iniciais estão preenchidas por 'f' 'o' 'o' 'b' 'a' 'r' '\0'. *PODES* utilizar uma varíavel no tamanho do array a criar - o tamanho desse array será o valor da variável, neste caso 30, e não o endereço.




"Esta sequência de instruções é perfeitamente válida" -> até ao primeiro segmention fault. Em C só se podes definir o tamanho do vector com CONSTANTES!
O compilador simplesmente não consegue saber o espaço de bar porque desconhece o valor de foo. Tão simples quanto isto... e não dá para explicar mais... se me vais mostrar um programa tipo este:

1º exemplo:

#include <stdio.h>

int main() {
int c = 30;
char vec[c];

vec[0] = 'a';
vec[1] ='b';
vec[2] = '\0';
printf("inicializei o vector\n");
printf("%s",vec);
}

para provares que funciona .. enfim eu digo-te experimenta este:

2º exemplo:
#include <stdio.h>

int main() {
char vec[2];

vec[0] = 'm';
vec[1] = 'a';
vec[2] = 'l';
vec[3] = '\0';
printf("inicializei o vector\n");
printf("%s",vec);
}

Asseguro-te que o printf mostra-te o que está escrito mas o que aconteceu neste exemplo, foi EXACTAMENTE o mesmo que aconteceu no 1º exemplo. Agora quando tiveres um programa maior , experimenta em declarar vectores sempre com variaveis e depois falamos do resultado.


Não ligues ao que o ZePinga te disse pois dali só saíram uma série de barbaridades. Fico abismado como um aluno do IST diz tanta coisa errada, ainda por cima para ajudar alguém que está somente a começar. O estrago que seria na vida do Sniper se eu não estivesse aqui... Enfim... ZePinga, talvez sejas do curso de Quimíca e como tal a tua falta de conhecimentos sobre a C seja compreensível - com o devido respeito a todos os Químicos que percebem bastante de programação.


O IST não é para aqui chamado. Para começar o meu curso é LEIC -- Licenciatura em engenharia informatica e computadores. O curso de LEQ/LQ (quimica) não sei o que tem a ver com o caso. Mas de certeza que não inicializam vectores com variaveis....

Disseste e fizeste um bom post até começares este paragrafo, "Nao ligues ao que..." . Daí para frente só saiu asneiras, reflecte com mais calma e respira fundo antes de escreveres :) .. .

" e como tal a tua falta de conhecimentos sobre a C seja compreensível", existe um livro de C, que é bastante conhecido Linguagem C do luís damas é em tuga e tudo. Compra-o e aprende a declarar vectores..


fica :roll:
IST, Lisbon DEI - LEIC
www.dei.ist.utl.pt
ZePinga
Aprendiz
Aprendiz
 
Mensagens: 98
Registado: Domingo Set 12, 2004 22:29

Mensagempor OmegaSquid » Segunda Fev 07, 2005 1:48

ZePinga percebes tanto de C como eu de contraplacados:

Código: Seleccionar todos
int b = 6;
char str[b];
strcpy(str,"moron");


Printa o vector e vê o impossivel...

Cya
Omega Squid 10k101
OmegaSquid
Novato
Novato
 
Mensagens: 6
Registado: Domingo Fev 06, 2005 0:29

Mensagempor ZePinga » Segunda Fev 07, 2005 1:50

Fica e para terminar o assunto!!!!


Um leitura sugestiva, caso não compres o Damas:

http://publications.gbdirect.co.uk/c_bo ... rrays.html

Onde se pode ler uma passagem:

"One important point about array declarations is that they don't permit the use of varying subscripts. The numbers given must be constant expressions which can be evaluated at compile time, not run time. For example, this function incorrectly tries to use its argument in the size of an array declaration:

f(int x){
char var_sized_array[x]; /* FORBIDDEN */
}"

It's forbidden because the value of x is unknown when the program is compiled; it's a run-time, not a compile-time, value.


Espero que para aproxima , não acuses os outros de ignorancia sem saberes bem se não és tu propria que tás a falhar :roll:


Fica,

sem ressentimentos , tudo cool :D

------------------------------

OmegaSquid Escreveu:ZePinga percebes tanto de C como eu de contraplacados:

Código: Seleccionar todos
int b = 6;
char str[b];
strcpy(str,"moron");


Printa o vector e vê o impossivel...

Cya


Quanto a ti basta olhar para o registo de quando de registaste aqui no forum.... :roll: lololololol
IST, Lisbon DEI - LEIC
www.dei.ist.utl.pt
ZePinga
Aprendiz
Aprendiz
 
Mensagens: 98
Registado: Domingo Set 12, 2004 22:29

Mensagempor OmegaSquid » Segunda Fev 07, 2005 2:15

Bem, tu deves tar parvo só pode... int b=6; eh que? run time?! vai plantar nabos... nao pera... enterra-te... ups... ou será que já te enterraste?

Nota-se mm que deves ter estudado pelo lamas, aquele livro eh a maior treta que ha pra C...

tho tudo dito...
hasta
Omega Squid 10k101
OmegaSquid
Novato
Novato
 
Mensagens: 6
Registado: Domingo Fev 06, 2005 0:29

Mensagempor jcorreia » Segunda Fev 07, 2005 2:23

Se tivesses lido o parágrafo seguinte do link que deste... Ora lê:

"It's forbidden because the value of x is unknown when the program is compiled; it's a run-time, not a compile-time, value."

No exemplo que usei:

int foo = 30;
char bar[foo];

A variável foo é... constante... em tempo de... compilação... TCHARAN! Pelo menos até ser declarado o array bar. O valor de foo quando bar é declarado é conhecido quando compilares o programa. Acho que não discordas disso.

Squid, também não é assim. O livro do Damas é um bom livro para quem não domina o inglês ou a programação em geral. A curva de aprendizagem é bastante mais leve que noutros livros como o "C Programming Language".

Enfim, ZePinga, espero que não te precipites nas respostas outra vez. Aconselho vivamente que comeces a praticar mais, e acima de tudo a tentar compreender o que se passa quando é avaliada cada instrução do teu programa em C. É um bom exercício. Começa por fazer um programa que conte caracteres e depois um que conte palavras. Se ainda não experimentaste faz um programinha que imprima "Hello, World". Se não te sentires confortável com o Inglês podes fazer "Olá, Mundo" que ninguém te chateia por isso.
jcorreia
Novato
Novato
 
Mensagens: 3
Registado: Sábado Fev 05, 2005 23:34

Mensagempor jaac » Segunda Fev 07, 2005 9:57

OmegaSquid Escreveu:ZePinga percebes tanto de C como eu de contraplacados:

Código: Seleccionar todos
int b = 6;
char str[b];
strcpy(str,"moron");


Printa o vector e vê o impossivel...

Cya


OmegaSquid Escreveu:Bem, tu deves tar parvo só pode... int b=6; eh que? run time?! vai plantar nabos... nao pera... enterra-te... ups... ou será que já te enterraste?

Nota-se mm que deves ter estudado pelo lamas, aquele livro eh a maior treta que ha pra C...

tho tudo dito...
hasta


Código: Seleccionar todos
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
  int b = 6;
  char str[b];
  strcpy(str,"moron");

  printf("%s\n", str);

  return 1;
}



Experimenta lá isto e vê se o output não é moron...

Quanto a ler o livro do damas ai concordo que não é dos melhores livros...

Quanto o int b = 6 e depois usar esse valor no vector não é run time contudo se programarem segundo a norma ansi vão ver que não recomendavel, eu só programa segundo o default ansi, é a melhor garantia que tenho que os programas vão funcionar na maior parte das plataformas...

E acho que alguém que já trabalho com C minimamente tem que admitir que a dificuldade do C é que quase tudo é possivel fazer até o que está mal às vezes funciona. Para terem uma ideia perdi 2 noites porque estava a perder 1bit em alguns ponteiros e tudo funciona bem até que a estrutura de dados atingir os 200kb (nao me perguntem porquê este valor)... acreditem é um pesadelo...
I never think of the future... it comes soon enough - Albert Einstein
jaac
Membro de Prata
Membro de Prata
 
Mensagens: 299
Registado: Quarta Ago 04, 2004 16:10

Mensagempor Puls3 » Segunda Fev 07, 2005 13:28

Boas... eu axo que vcs deviam ler melhor as threads uns dos outros... tão a falar de coisas diferentes :) É apenas uma questão do que se pode fazer... o q se deve fazer... e o k n se deve fazer... viva ao C! :roll:
Puls3
Novato
Novato
 
Mensagens: 16
Registado: Quinta Jan 01, 2004 17:42

Mensagempor Tretabyte » Segunda Fev 07, 2005 15:09

Boas,
acho que anda ai alguem que precisa de acalmar a passarinha.

sem mais
Tretabyte
Avatar do Utilizador
Tretabyte
Gurus
Gurus
 
Mensagens: 5333
Registado: Sábado Jan 17, 2004 13:17
Localização: Lx

Mensagempor ZePinga » Segunda Fev 07, 2005 20:28

jcorreia Escreveu:Se tivesses lido o parágrafo seguinte do link que deste... Ora lê:

"It's forbidden because the value of x is unknown when the program is compiled; it's a run-time, not a compile-time, value."

No exemplo que usei:

int foo = 30;
char bar[foo];

A variável foo é... constante... em tempo de... compilação... TCHARAN! Pelo menos até ser declarado o array bar. O valor de foo quando bar é declarado é conhecido quando compilares o programa. Acho que não discordas disso.


Boas,

Não é em runtime.. porque é uma variavel . Eu já percebi onde errei e originou confusão , expliquei uma coisa e dei maus exemplos num dos replies que fiz, eu já explico onde.
Em relação a esta questão da variavel ser em runtime e para responder ao lame do OmegaSquid que fez dois posts e nos dois se enganou tanto no codigo como nas respostas....

Vou vos esclarecer dando primeiro um exemplo claro de runtime e depois um exemplo mais complicado que depois de desmembrado se vê bem que é em runtime.

1º exemplo de que é em runttime:

#include <stdio.h>
main(){
srand(time(NULL));
int a = (int)(rand()%10);
char b[a];
printf( "%d\n", sizeof( b ) );
}

Ouput:

vador@Corbin:~ $ ./teste
7
vador@Corbin:~ $ ./teste
5
vador@Corbin:~ $ ./teste
9

Acho que não restam duvidas de que é em runtime, neste exemplo. Porque se o compilador tivesse de saber o valor da variavel, daria erro na compilação o que não acontece e por consequinte só em runtime é que se sabe o valor.


2º Exemplo como o Omega squid gosta...
f(){
int b = 6;
char c[b ];
}
main(){
f();
}

Não vai ter output pq eu quis simplificar o codigo e concerteza concordo com voces o sizeof vai ser neste exemplo, sempre igual. Mas é em runtime!!!

Vamos desmembrar o nosso exemplo e ver isto instrução a instrução:

.file "teste3.c"
.text
.globl f
.type f, @function
f:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl %esp, %edx
movl $6, -4(%ebp)
movl -4(%ebp), %eax
decl %eax
incl %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl %edx, %esp
leave
ret
.size f, .-f
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
call f
leave
ret
.size main, .-main
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.3.5 (Debian 1:3.3.5-6ubuntu1)"


Vamos nós focar na função f() que é onde esta o que é pretendido.
A variavel int b é alocada no epílogo da função:
subl $8, %esp

O b = 6 é feito de seguida:

movl $6, -4(%ebp)

tá a 4bytes do BasePointer , nesta instrução:
movl -4(%ebp), %eax

aqui coloca o valor em AX (registo). Depois faz umas operações com o registo irrelevantes para aqui e saltamos para a instrução de alocação do espaço em runtime o (char[b ]):

subl %eax, %esp

o programa aumenta o stack em AX valores, de lembrar que AX é´o valor de b. E depois ele restora esse espaço, fim da instrução. Se estas ainda com duvidas em relação a isto epa cria um programa em C, faz man de gcc e verifica para que é que serve a flag -S.

Em relação a isto nada mais digo. E tu OmegaSquid faz refresh ao teu proxy e lava a boca , não tamos aqui para ofender ninguem , mas sim para discutir e aprender uns com os outros (nota: é discutindo que se vai aprendendo mas tu és mais a base de mandar abaixo os outros, ñ sei deves sentir superior ou assim enfim, atitudes mto lames na minha optica).

Um parentisis eu aprendi C lendo o Kernighan e praticando muito , tambem tenho o Damas, não é mau de todo. Acho que uma mistura dos dois mais os manuais das bibliotecas e muito trabalho é o caminho a seguir para saber-se C mais avançado.


O reply onde me enganei foi onde dei este exemplo:
1º exemplo:

#include <stdio.h>

int main() {
int c = 30;
char vec[c];

vec[0] = 'a';
vec[1] ='b';
vec[2] = '\0';
printf("inicializei o vector\n");
printf("%s",vec);
}


De facto e como já disse é em run-time mas neste exemplo o vec[c] é smp 30 porque deveria ter metido deste modo:
#include <stdio.h>

int main() {
int c = 30;
...........
char vec[c];

vec[0] = 'a';
vec[1] ='b';
vec[2] = '\0';
printf("inicializei o vector\n");
printf("%s",vec);
}

Onde ....... significa que pode haver instruções onde C poderá ser modificado sendo assim á partida o compilador ñ sabe o valor de C e só em runt-time aloca o vec[c]. Foi isto que eu disse mas com e admito um pessimo exemplo.


Fiquem....
Editado pela última vez por ZePinga em Terça Fev 08, 2005 14:07, num total de 1 vez.
IST, Lisbon DEI - LEIC
www.dei.ist.utl.pt
ZePinga
Aprendiz
Aprendiz
 
Mensagens: 98
Registado: Domingo Set 12, 2004 22:29

Próximo

Voltar para Programação

Quem está ligado:

Utilizador a ver este Fórum: Nenhum utilizador registado e 1 visitante

cron