Falha de Segmentação (Imagem do núcleo gravada)

1. Falha de Segmentação (Imagem do núcleo gravada)

Henrique dos Santos Dias Mattos
henriquesdm7

(usa Ubuntu)

Enviado em 03/05/2018 - 15:53h

Então gente, eu sou novo no fórum, e também na programação.
Eu to tentando aprender a usar arquivos para salvar e receber dados então fiz esse programa:
#include <stdio.h>
#include <stdlib.h>

typedef struct{
char nome[80], sexo;
int idade, id;
}dados;

int main(){
FILE *arquivo;
arquivo = fopen ("arquivo.txt", "w+");
if (arquivo == NULL) {
printf ("Houve um erro ao abrir o arquivo.\n");
return 0;
}
// DEFINICAO DAS VARIAVEIS
int nalunos, nsalas, j, i;
dados aluno[nsalas][nalunos];

// INICIO DO PROGRAMA
printf("ENTRE COM O NUMERO DE SALAS: \n");
scanf("%d", &nsalas);
for(i=0; i<nsalas; i++) {
printf("\nENTRE COM O NUMERO DE ALUNOS NA SALA %d: ", i+1);
scanf("%d", &nalunos);
for(j=0; j<nalunos; j++){
printf("\nALUNO %d \n", j+1);
printf("Nome do aluno : ");
scanf(" %[^\n]s", &aluno[i][j].nome);
printf("Sexo (m ou f) : ");
scanf(" %c", &aluno[i][j].sexo);
printf("Idade do aluno em anos : ");
scanf("%d", &aluno[i][j].idade);
printf("Numero da ID do aluno : ");
scanf("%d", &aluno[i][j].id);
}
}
printf("\n\n\n");

for (i=0; i<nsalas; i++){
printf("\n\tSALA %d", i+1);
for (j=0; j<nalunos; j++){
printf("\nAluno %d", j+1);
printf("\nNOME: %s", aluno[i][j].nome);
printf("\nSEXO: %s", aluno[i][j].sexo);
printf("\nIDADE: %d", aluno[i][j].idade);
printf("\nID: %d \n", aluno[i][j].id);
}
}
fclose (arquivo);
system("pause");
return 0;
}

No meio do programa aparece essa "falha de segmentação", e dependendo de onde eu coloco a variável FILE, ele aparece em local diferente. Como resolvo, e por que dá erro?


  


2. Re: Falha de Segmentação (Imagem do núcleo gravada)

Paulo
paulo1205

(usa Ubuntu)

Enviado em 03/05/2018 - 17:05h

henriquesdm7 escreveu:

     int nalunos, nsalas, j, i;
dados aluno[nsalas][nalunos];


Quando você declara nalunos e nsalas de modo automático, os valores iniciais dessas variáveis são desconhecidos. Assim sendo, esses valores desconhecidos entram na declaração de alunos — você declara uma matriz de tamanho desconhecido.

Isso pode ser um problema algumas linhas mais tarde, quando você começar a popular essa matriz, e é uma boa candidata a ser a causa do seu SIGSEGV,


3. Re: Falha de Segmentação (Imagem do núcleo gravada)

Henrique dos Santos Dias Mattos
henriquesdm7

(usa Ubuntu)

Enviado em 04/05/2018 - 07:33h

paulo1205 escreveu:

henriquesdm7 escreveu:

     int nalunos, nsalas, j, i;
dados aluno[nsalas][nalunos];


Quando você declara nalunos e nsalas de modo automático, os valores iniciais dessas variáveis são desconhecidos. Assim sendo, esses valores desconhecidos entram na declaração de alunos — você declara uma matriz de tamanho desconhecido.

Isso pode ser um problema algumas linhas mais tarde, quando você começar a popular essa matriz, e é uma boa candidata a ser a causa do seu SIGSEGV,


Obrigado pela dica Paulo, arrumei aqui e vou começar a utilizar assim daqui pra frente. Acabei de compilar e executar e ainda dá falha de segmentação no mesmo local.


4. Re: Falha de Segmentação (Imagem do núcleo gravada)

Paulo
paulo1205

(usa Ubuntu)

Enviado em 04/05/2018 - 07:54h

Com o programa que você mostrou, não vi nenhum outro problema além daquele que eu lhe indiquei. Você suprimiu alguma parte quando transcreveu o programa aqui? Pergunto porque, em particular, não vi você escrever nem ler o arquivo em momento nenhum.

Mostre como ficou o programa depois da alteração. Pode ser que ainda haja alguma coisa errada.


5. Re: Falha de Segmentação (Imagem do núcleo gravada)

Henrique dos Santos Dias Mattos
henriquesdm7

(usa Ubuntu)

Enviado em 04/05/2018 - 11:51h

Então, depois da alteração, o programa completo ficou assim:
#include <stdio.h>
#include <stdlib.h>

typedef struct{
char nome[80], sexo;
int idade, id;
}dados;

int main(){
FILE *arquivo;
arquivo = fopen ("arquivo.txt", "w+");
if (arquivo == NULL) {
printf ("Houve um erro ao abrir o arquivo.\n");
return 0;
}
// DEFINICAO DAS VARIAVEIS
int nalunos = 0, nsalas = 0, j, i;
dados aluno[nsalas][nalunos];

// INICIO DO PROGRAMA
printf("ENTRE COM O NUMERO DE SALAS: \n");
scanf("%d", &nsalas);
for(i=0; i<nsalas; i++) {
printf("\nENTRE COM O NUMERO DE ALUNOS NA SALA %d: ", i+1);
scanf("%d", &nalunos);
for(j=0; j<nalunos; j++){
printf("\nALUNO %d \n", j+1);
printf("Nome do aluno : ");
scanf(" %[^\n]s", &aluno[i][j].nome);
printf("Sexo (m ou f) : ");
scanf(" %c", &aluno[i][j].sexo);
printf("Idade do aluno em anos : ");
scanf("%d", &aluno[i][j].idade);
printf("Numero da ID do aluno : ");
scanf("%d", &aluno[i][j].id);
}
}
printf("\n\n\n");

for (i=0; i<nsalas; i++){
printf("\n\tSALA %d", i+1);
for (j=0; j<nalunos; j++){
printf("\nAluno %d", j+1);
printf("\nNOME: %s", aluno[i][j].nome);
printf("\nSEXO: %s", aluno[i][j].sexo);
printf("\nIDADE: %d", aluno[i][j].idade);
printf("\nID: %d \n", aluno[i][j].id);
}
}
fclose (arquivo);
system("pause");
return 0;
}

Nem consigo imaginar o que estaria causando esse erro.


6. Re: Falha de Segmentação (Imagem do núcleo gravada)

Paulo
paulo1205

(usa Ubuntu)

Enviado em 04/05/2018 - 17:55h

Você continua com problemas na hora de alocar o array. Antes, você o estava alocando com tamanho indeterminado; agora, está alocando com tamanhos iguais a zero, o que é ilegal de acordo com o padrão do C, mas é suportado pelo GCC como uma extensão fora do padrão, com sentido que, nesse caso específico, é igual a alocação com tamanhos iguais a 1.

E seu programa tem outro erro: você lê uma quantidade potencialmente diferente de alunos em cada sala, mas não armazena a quantidade de alunos de cada sala em lugar nenhum. Na hora de imprimir, seu programa aplica a todas as salas a quantidade de alunos da última sala, pois esse é o último valor atribuído à variável nalunos.

Como consertar seu programa?

Se todas as salas tiverem a mesma quantidade de alunos, você pode ler antecipadamente, fora de qualquer laço de repetição, tanto a quantidade de salas quanto a de alunos por sala, e, somente depois de ter esses valores garantidos, declarar uma matriz, usando a sintaxe de VLAs (variable-length arrays, disponível desde o C99).

Um problema com VLAs, contudo, é que eles são alocados na pilha, que costuma ter mais restrições de tamanho do que a memória disponível para alocações dinâmicas. Se a quantidade de dados for muito grande, essa opção pode ser inviável, mesmo que seu compilador a suporte.

Se seu compilador for anterior a 1999 (ou, no caso do Visual Studio, anterior a 2015), se você tiver muitos dados (a ponto de exceder o tamanho da pilha), se cada sala puder ter uma quantidade diferente de alunos ou se você quiser trabalhar de uma forma mais genérica, você teria de usar alocação dinâmica. Seu programa teria de ter uma forma mais ou menos parecida com a seguinte.

dados **aluno;
size_t nsalas, *nalunosporsala;

/* Descobre o número de salas e o guarda em ‘nsalas’. */
nalunosporsala=malloc(nsalas * sizeof *nalunosporsala);
aluno=malloc(nsalas * sizeof *aluno);
if(!nalunoporsala || !aluno){
fputs("Erro de alocação de memória.\n", stderr);
exit(1);
}

/* LEITURA */
for(size_t n=0; n<nsalas; n++){
/* Descobre a quantidade de alunos na sala n e a guarda em ‘nalunosporsala[n]’. */
aluno[n]=malloc(nalunosporsala[n] * sizeof *aluno[n]);
if(!aluno[n]){
fputs("Erro de alocação de memória.\n", stderr);
exit(1);
}
for(size_t m=0; m<nalunosporsala[n]; m++){
/* Lê dados do aluno[n][m]. */
}
}

/* IMPRESSÃO */
for(size_t n=0; n<nsalas; n++){
printf("Sala %zu tem %zu alunos:\n", n, nalunosporsala[n]);
for(size_t m=0; m<nalunosporsala[n]; m++){
/* Imprime dados do aluno[n][m]. */
}
}

/* FINALIZAÇÃO: Você deve devolver a memória que alocou dinamicamente quando não for mais usá-la. */
while(nsalas)
free(aluno[--nsalas]);
free(aluno);
free(nalunosporsala);







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts