Ir ao conteúdo

Segmentation Fault em Malloc - Lista Encadeada


rs.fran

Posts recomendados

Postado

Oi gente, tudo bem?

Estou desenvolvendo um trabalho de faculdade e tenho que implementar uma agenda de compromissos em C. O problema é que ao tentar inserir o compromisso que o usuario digita na agenda, aparece a mensagem segmentation fault na linha do malloc. Usei o gdb para verificar e é exatamente nessa linha. Segue o código:

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <string.h>

#define InicioArranjo 1

#define MaxTam 12

/*ESTRUTURAS */

typedef struct compromisso_s { //estrutura que defique cada variavel que estara contida em uma celula de compromisso

int dia, mes, ano, duracao, hora, minuto, tipo, status, adiavel, adiado, id, prioridade;

char nome [100];

} compromisso;

typedef struct Celula_str *Apontador; //estrutura que define uma apontador para a celula

typedef struct Celula_str { //estrutura que define o que esta contido dentro da celula (estrutura compromisso e um apontador que aponta para o proximo )

compromisso item;

Apontador prox;

} celula;

typedef struct { //descritor

Apontador Primeiro, Ultimo;

} TipoLista;

typedef struct Ag{ // estrutura que define o que esta contido dentro de uma agenda

int id_ag;

char nome [100];

int ano;

TipoLista Lista;

} agenda;

/*OPERAÇÕES PARA LISTA DE COMPROMISSOS*/

void FLVazia(TipoLista *Lista) { //cria uma lista vazia

Lista->Primeiro = (Apontador) malloc(sizeof(celula));

Lista->Ultimo = Lista->Primeiro;

Lista->Primeiro->prox = NULL;

}

int Vazia(TipoLista *Lista) { //verifica se uma lista esta vazia

return (Lista->Primeiro == Lista->Ultimo);

}

void Insere(TipoLista *Lista, int dia,char nome[100], int mes,int ano,int duracao,int hora,int minuto,int tipo,int status,int adiavel,int adiado,int id,int prioridade) { //insere uma celula de compromisso na lista e aponta pra uma nova celula inicialmente vazia

Lista->Ultimo->prox = (Apontador) malloc(sizeof(celula));

Lista->Ultimo = Lista->Ultimo->prox;

Lista->Ultimo->item.mes = mes;

Lista->Ultimo->item.dia = dia;

Lista->Ultimo->item.ano = ano;

Lista->Ultimo->item.duracao = duracao;

Lista->Ultimo->item.hora = hora;

strcpy (nome,Lista->Ultimo->item.nome);

Lista->Ultimo->item.minuto = minuto;

Lista->Ultimo->item.tipo = tipo;

Lista->Ultimo->item.status = status;

Lista->Ultimo->item.adiavel = adiavel;

Lista->Ultimo->item.adiado = adiado;

Lista->Ultimo->item.id = id;

Lista->Ultimo->item.prioridade = prioridade;

Lista->Ultimo->prox = NULL;

}

void inicializaCompromisso(int i, int id, struct Ag *x, TipoLista Lista){ // recebe as informações associadas de um novo compromisso, que deve ser inicializado e inserido na agenda. A operacao deve imprimir uma mensagem informando sucesso ou falha. Em caso de sucesso,o identificador do compromisso deve ser impresso.

int dia, mes, ano, duracao, hora, minuto, tipo, status, adiavel, adiado, prioridade;

char nome[100];

printf("Por favor, digite o tipo de compromisso a ser cadastrado. (Escolha um numero: 1-Aula, 2-Orientacao, 3-Reuniao, 4-Evento ou 5-Compromisso particular.");

scanf("%d", &tipo);

while ((tipo != 1) && (tipo != 2) && (tipo != 3) && (tipo != 4) && (tipo != 5)){

printf("Desculpe, mas o tipo de compromisso digitado nao e valido. Por favor, escolha um numero: 1-Aula, 2-Orientacao, 3-Reuniao, 4-Evento ou 5-Compromisso particular.");

scanf("%d", &tipo);

}

printf("Digite um nome para identificar seu compromisso\n");

gets(nome);

printf("Agora digite a data de seu compromisso no formato dd/mm/aaaa\n");

scanf("%d/%d/%d", &dia, &mes, &ano);

if (tipo == 4){

printf("Digite a duracao de seu compromisso em dias:\n");

scanf("%d", &duracao);

}

else{

printf("Digite a duracao de seu compromisso em minutos:\n");

scanf("%d", &duracao);

}

printf("Digite a Hora: \n ");

scanf("%d", &hora);

printf("Digite os Minutos: \n ");

scanf("%d", &minuto);

switch(tipo){

case 1:

prioridade = 2;

adiavel = 0;

break;

case 2:

prioridade = 1;

adiavel = 1;

break;

case 3:

prioridade = 4;

adiavel = 1;

break;

case 4:

prioridade = 3;

adiavel = 0;

break;

case 5:

prioridade = 2;

adiavel = 1;

break;

}

status=1;

adiado=0;

Insere(&x.Lista, dia, nome, mes, ano, duracao, hora, minuto, tipo, status, adiavel, adiado, id, prioridade);

}

void acessa_agenda(struct Ag *x){

int id, opcao_menuComp, lerID, i, existe;

compromisso c;

Apontador p;

id = 0;

do{

printf("Digite o numero de identificacao da sua agenda:\n");

scanf("%d", &lerID);

for (i=0; i<12; i++){

if (x.id_ag == lerID){

printf("Ola %s.", x.nome);

existe = 1;

break;

}

else {

printf("Agenda nao existente");

existe = 0;

}

}

} while ((existe = 0));

printf(" Esta e sua agenda eletronica. O que deseja fazer?\n");

printf("1) Inserir novo compromisso\n");

printf("2) Alterar compromisso\n");

printf("3) Excluir compromisso\n");

printf("4) Buscar e exibir compromissos por id\n");

printf("5) Exibir compromissos a cumprir/Total a cumprir\n");

printf("6) Exibir compromissos adiados/Total de adiados\n");

printf("7) Exibir compromissos cancelados/Total de cancelados\n");

printf("8) Visualizar agenda a partir de data especificada\n");

printf("9) Visualizar agenda completa\n");

printf("10) Resolver conflitos (essa funcao adia ou cancela automaticamente compromissos que possuem hora e/ou data iguais considerando a prioridade dos mesmos).\n");

printf("11) Encerrar sessão e sair do sistema\n");

scanf("%d", &opcao_menuComp);

switch (opcao_menuComp){

case 1:

id++;

inicializaCompromisso(i, id, x, x.Lista);

break;

case 2:

alteraCompromisso(&c, x, &x.Lista);

break;

case 3:

excluiCompromisso(p, &x.Lista, &c);

break;

case 4:

imprimeCompromisso(&c, x, x.Lista);

break;

case 5:

imprimeContaCumprir(&c, x, x.Lista);

break;

case 6:

imprimeContaAdiados(&c, x, x.Lista);

break;

case 7:

imprimeContaCancel(&c, x, x.Lista);

break;

//case '8':

// VerPorData();

// break;

case 8:

resolveConflito(x.Lista, &c);

break;

case 9:

Imprime(x.Lista);

break;

case 10:

break;

}

}

int main (){

int opcao_menu1, i,j;

struct Ag vetor[12];

TipoLista Lista;

j=0;

FLVazia(&Lista);

Vazia(&Lista);

if (Vazia(&Lista)) printf("lista vazia");

for (i=0; i<12; i++){

vetor.id_ag = i + 1;

}

do{

printf("Bem vindo a sua agenda eletronica.\n");

printf("Escolha uma das opções abaixo:(Digite o numero correspondente a opcao desejada e pressione enter para confirmar.\n");

printf("1) Criar nova agenda vazia\n");

printf("2) Acessar agenda existente\n");

printf("3) Sair do sistema\n");

opcao_menu1 = getchar();

switch (opcao_menu1){

case '1':

InsereAgenda(vetor,j);

break;

case '2':

acessa_agenda(vetor);

break;

case '3':

return(0);

break;

}

} while ((opcao_menu1 >= 3) || (opcao_menu1 <= 0));

return(0);

}

Essas são apenas as funções que se relacionam com o problema em questão. Como o programa completo tem muitas, não postei as outras. Usando um breakpoint na função inicializaCompromisso recebo o erro segmentation fault na linha 47 (na função insere, como o malloc).. será que estou passando parâmetros errados?

Alguém pode ajudar?

Postado

rs.fran acho que o problema da linha 47 é que você faz o malloc de sizeof(celula) e guarda em um Apontador, que tem tamanhos diferentes. Teste com:


printf("%ld\n", sizeof(celula));
printf("%ld\n", sizeof(Apontador));

Tenta fazer:

Lista->Ultimo->prox = (Apontador) malloc(sizeof(Apontador));

Não testei nada então não garanto nada, só tentando dar uma luz, hahaha

Postado

Obrigada pela resposta, sepoki. Infelizmente não funcionou.. usei o Valgrind pra tentar descobrir, é erro de memória mesmo, acusou nele, só não sei resolver rs.

Segue o relatório:

==4846== Use of uninitialised value of size 4

==4846== at 0x804860A: Insere (teste1fran.c:47)

==4846== by 0x8048A88: inicializaCompromisso (teste1fran.c:142)

==4846== by 0x804A0B0: acessa_agenda (teste1fran.c:641)

==4846== by 0x804A405: main (teste1fran.c:702)

==4846== Uninitialised value was created by a stack allocation

==4846== at 0x804A2F2: main (teste1fran.c:674)

==4846==

==4846==

==4846== Process terminating with default action of signal 11 (SIGSEGV)

==4846== Bad permissions for mapped region at address 0x400D20C

==4846== at 0x804860A: Insere (teste1fran.c:47)

==4846== by 0x8048A88: inicializaCompromisso (teste1fran.c:142)

==4846== by 0x804A0B0: acessa_agenda (teste1fran.c:641)

==4846== by 0x804A405: main (teste1fran.c:702)

==4846==

==4846== FILE DESCRIPTORS: 3 open at exit.

==4846== Open file descriptor 2: /dev/pts/0

==4846== <inherited from parent>

==4846==

==4846== Open file descriptor 1: /dev/pts/0

==4846== <inherited from parent>

==4846==

==4846== Open file descriptor 0: /dev/pts/0

==4846== <inherited from parent>

==4846==

==4846==

==4846== HEAP SUMMARY:

==4846== in use at exit: 156 bytes in 2 blocks

==4846== total heap usage: 2 allocs, 0 frees, 156 bytes allocated

==4846==

==4846== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2

==4846== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)

==4846== by 0x8048609: Insere (teste1fran.c:47)

==4846== by 0x8048A88: inicializaCompromisso (teste1fran.c:142)

==4846== by 0x804A0B0: acessa_agenda (teste1fran.c:641)

==4846== by 0x804A405: main (teste1fran.c:702)

==4846==

==4846== 152 bytes in 1 blocks are still reachable in loss record 2 of 2

==4846== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)

==4846== by 0x80485B5: FLVazia (teste1fran.c:37)

==4846== by 0x804A311: main (teste1fran.c:681)

==4846==

==4846== LEAK SUMMARY:

==4846== definitely lost: 4 bytes in 1 blocks

==4846== indirectly lost: 0 bytes in 0 blocks

==4846== possibly lost: 0 bytes in 0 blocks

==4846== still reachable: 152 bytes in 1 blocks

==4846== suppressed: 0 bytes in 0 blocks

==4846==

==4846== For counts of detected and suppressed errors, rerun with: -v

==4846== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Falha de segmentação (imagem do núcleo gravada)

Postado

Jogando videogame cara dá pra ver que esse cast está errado.

Normalmente gosto de testar antes, mas dar cast de um bloco struct para um tipo ponteiro é osso.

Arruma esse cast campeão, se você pediu um sizeof celula o cast deve ser celula.

Você usa aquilo que você aloca, o cast está lá apenas para converter a memória de RAW para o tipo que você deseja usar.

Um ponteiro tem sempre 4 bytes na plataforma 32 bits, não faz o mínimo sentido esse cast.

Devem ter mais erros, esse código está horroroso, mas esse segmentation fault foi cast errado.

Postado

Obrigada pela ajuda, já consegui resolver.. Era um parâmetro errado mesmo. Quanto ao meu código, to no 2º periodo de computação, tenho tempo para aprender a fazer ele bonito, né? haha ^_^

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!