Segmentation failure (recorded nucleus image)

Asked

Viewed 1,043 times

0

I’m doing a college job, I did the code, it’s working normally on windows. In Ubuntu it is compiling, when I start using the Inserts function, it gives this error that is in the subject.

Just follow my code:

#define N 11
int tamanho = 1; //Numero de inserções

typedef struct pessoa{
int idadep;
char nomep[20];
char enderecop[20];
struct pessoa *prox;
}Pessoa;

void inicializa(Pessoa **p){
*p = NULL;
}

int iq(char Nome[]);

void insere(Pessoa **p, char nome[], int idade, char endereco[]){
Pessoa *ultimo,*aux,*penultimo;
int i = 0;
tamanho++;
// printf("inserindo %s no vetor de posicao %d\n",nome,iq(nome));

aux = (Pessoa*) malloc(sizeof(Pessoa));
ultimo = (Pessoa*) malloc(sizeof(Pessoa));
penultimo = (Pessoa*) malloc(sizeof(Pessoa));

if (*p == NULL){
//  printf("nulo\n");
strcpy(ultimo->nomep,nome);
ultimo->idadep = idade;
strcpy(ultimo->enderecop,endereco);
ultimo->prox = NULL;
*p = ultimo;

}
else{
penultimo = *p;
ultimo = *p;
while(ultimo != NULL){
if(strcmp(nome,ultimo->nomep) < 0){//nome tem que ficar antes de ultimo->nome
strcpy(aux->nomep,nome);
aux->idadep = idade;
strcpy(aux->enderecop,endereco);
aux->prox = ultimo;
if(i == 0)
*p = aux;
else{
penultimo->prox = aux;
}
break; //sai do while
}
else if(strcmp(nome, ultimo->nomep) == 0) //O nome a ser inserido já existe na lista
return;
else{ //nome tem que ficar depois de ultimo->nome
if(ultimo->prox == NULL){ //chegou ao final, então insere ele no final
strcpy(aux->nomep,nome);
aux->idadep = idade;
strcpy(aux->enderecop,endereco);
aux->prox = NULL;
ultimo->prox = aux;
break;
}
penultimo = ultimo;
ultimo = ultimo->prox;
}
i++;
}
}
}

void consulta(Pessoa **p, char nome[]){
Pessoa *aux;
aux = *p;
while(aux != NULL){
if (strcmp(aux->nomep, nome) == 0){
printf("%s\n", aux->nomep);
printf("%d\n", aux->idadep);
printf("%s\n", aux->enderecop);
}
aux = aux->prox;
}
}

void Remove(Pessoa** p, char nome[] ){
Pessoa* ant, * aux;
ant = NULL;
aux = *p;
while(aux != NULL && strcmp(aux->nomep, nome) !=0){
ant = aux;
aux = aux->prox;
}
if (aux == NULL || p == NULL){
return;
}
else if(ant == NULL && strcmp(aux->nomep, nome) ==0){ //tá no primeiro elemento
*p = aux->prox;
}
else if(aux->prox == NULL && strcmp(aux->nomep, nome) ==0){
ant->prox = NULL;
}
else{
ant->prox = aux->prox;
}
}

void print(Pessoa **p){
Pessoa *aux;
aux = *p;
while (aux != NULL){
printf("%s \n", aux->nomep);
//printf("%d \n", aux->idadep);
//printf("%s \n", aux->enderecop);
aux = aux->prox;
}
}


int ordc(char LetraNome){
int x;

if(LetraNome == ' ')
return 27;
else{
if(LetraNome >= 65 && LetraNome <= 90) //Entre A e Z
x = LetraNome - 64;
else //Entre a e z
x = LetraNome - 96;
}
return x;
}

int iq(char Nome[]){
int i, rordc = 0;

for(i = 0; i < strlen(Nome); i++){
rordc += ordc(Nome[i]);
}
return rordc%N;
}

void criaHeap(Pessoa *vet, int i, int f){
Pessoa aux = vet[i];
int j = i * 2 + 1;
while (j <= f){
if(j < f){
if(strcmp(vet[j].nomep,vet[j + 1].nomep) < 0){
j = j + 1;
}
}
if(strcmp(aux.nomep, vet[j].nomep) < 0 ){
vet[i] = vet[j];
i = j; //j é o novo pai
j = 2 * i + 1;
}else{
j = f + 1;
}
}
vet[i] = aux;
}

void heapSort(Pessoa *vet, int n){
int i;
Pessoa aux;
for(i=(n - 1)/2; i >= 0; i--){
criaHeap(vet, i, n-1);
}
for (i = n-1; i >= 1; i--){
aux = vet[0];
vet [0] = vet [i];
vet [i] = aux;
criaHeap(vet, 0, i - 1);
}
}

int salvaLista(Pessoa* v, int tamV, Pessoa** p){
Pessoa *aux;
aux = *p;
int i = tamV;
while (aux != NULL){
strcpy(v[i].nomep,aux->nomep);
v[i].idadep = aux->idadep;
strcpy(v[i].enderecop,aux->enderecop);
aux = aux->prox;
i++;
}
return i;
}

void imprimeTudo(Pessoa **p){
Pessoa* copia = (Pessoa*) malloc(sizeof(Pessoa)*tamanho);
int tam = 0, in;
for(in = 0 ; in < N; in++)
tam = salvaLista(copia,tam,&p[in]);
heapSort(copia,tam);
for(in = 0 ; in < tam; in++)
printf("%s\n", copia[in].nomep);
}

int main(){
int indice, idade, qtd, in = 0;
char metodo, nome[20], endereco[20];
Pessoa **p = (Pessoa**) malloc(sizeof(Pessoa*)*N);
for(in = 0; in < N; in++)
inicializa(&p[in]);
while(metodo != 'e'){
scanf("%c", &metodo);
switch(metodo){
case 'i':
fflush(stdin);
scanf("%d", &qtd);
for(in = 0; in < qtd; in++){
fflush(stdin);
gets(nome);
fflush(stdin);
scanf("%d",&idade);
fflush(stdin);
gets(endereco);
fflush(stdin);
insere(&p[iq(nome)], nome, idade, endereco);
}
break;
case 'r':
fflush(stdin);
gets(nome);
Remove(&p[iq(nome)], nome);
break;
case 'c':
fflush(stdin);
gets(nome);
consulta(&p[iq(nome)], nome);
break;
case 'l':
fflush(stdin);
scanf("%d", &indice);
print(&p[indice]);
break;
case 'o':
fflush(stdin);
imprimeTudo(p);
break;
}

}

return 0;
}
  • C or C++, what is the language?

  • The work should be in C

  • Where exactly are you going wrong? Enjoy and do the tour to learn about the operation and rules of the website.

  • I’m sorry, I was editing the title when they edited it for me, it’s just that I’ve been suffering from this error for 6 hours at least, and I didn’t even pay attention... So my code compiles, after that I’ll use the insert, type "i" and start inserting, for example: i 4 Matheus 20 street test

1 answer

1


You are forgetting to initialize a lot of local variables as well as check the sizes of the entries you are receiving, and this can generate segmentation failure depending on what input you write to your program. Let’s follow the Chinese:

  1. You get into main(). Creates the local variables:

    • indice (worthless),
    • idade (worthless),
    • qtd (worthless),
    • in (0),
    • metodo (worthless),
    • nome (vector of 20 chars, with garbage),
    • endereco (vector of 20 chars, with garbage),
    • p (array of N pointers to structs Pessoa).
  2. Reboot in with zero and uses it to iterate on p, calling for inicializa() on each element of that vector. inicializa(), in turn, merely attributes the p[in] the value NULL.

  3. gets into a while hoping that metodo be equal to 'e' - note that, as metodo was not initialized, there is 1 chance in 256 that the memory space of metodo contains the byte 0x65, causing the program to mysteriously terminate its operation immediately.

  4. User information is obtained (without prompt) on which operation is to be executed; the user presses i [enter], and the system continues.

  5. The system makes a switch on the value of metodo, and gets into the business case 'i':, immediately discarding the remaining values in stdin. This is great for interactive treatment, but if the user decides to redirect stdin to automate your typing, here the prepared and redirected file entry is thrown out, and the program reaches an impasse.

  6. The system fills in the variable nome using gets() (again without , which means that if the user enters a name with more than 19 characters, the system has entered buffer overflow and will start overwriting the other local variables in the stack.

  7. The system again discards the rest of input into stdin using fflush() and waiting (without prompt) the user enters a number, whose validity is also not verified. If the user does not enter a number here, the variable idade will continue to contain trash and execution will follow.

  8. The system, once again, discards the rest of the input and waits (without prompt) the user enters an address; again, if the user enters an address with more than 19 characters, the system will overwrite the other local variables, the buffer of nome and possibly even the return address of main().

  9. The system tries to insert (nome, idade, endereço) in the cell iq(nome) of p:

    1. iq() iterates on the elements of nome, accumulating the values of ordc(nome[i]) starting with 0.

      1. ordc(), in turn, returns the alphabetical value of each letter A-Z or a-z uppercase or lowercase, or return 27 to a space. For accented characters like 'á' or 'ç', ordc() returns the uninitialized value of x.
    2. iq() finally returns the module accumulated result the number of houses in p. In the case of the test name Matheus, it returns 13 + 1 + 20 + 8 + 5 + 21 + 19 = 87 mod 11 = 10.

  10. insere() starts running, receiving the address of p[10], Matheus, 20 and Rua Teste in p, nome, idade and endereço, respectively. The following local variables are created:

    • ultimo, pointer to Person (pointing to a random segment of memory);
    • aux, ditto;
    • penultimo, Ibidem;
    • i, integer (value 0).
  11. The global tamanho, that was initialized in memory with 1, incremented to 2.

  12. aux, ultimo and penultimo each receives an object in memory allocated via malloc().

  13. The system checks whether the position of p is empty. As is, we enter the first branch.

  14. nome is copied to ultimo->nomep using strcpy(), which will overwrite the rest of the structure if nome has more than 19 characters, but in this case no.

  15. endereco is also copied to ultimo->enderecop using strcpy(), opening up the possibility of buffer overflow, and idade is also copied to ultimo->idadep. The position of p points to ultimo and the system returns, without dislocating penultimo and aux that were allocated unnecessarily, generating a memory leak.

  16. The system comes out of insere(), back to the top of the for, eliminates the rest of the input and waits (without prompt) the entry of the second name. However, before that you state that, in Ubuntu, the program stops with a segmentation fault, which means that it is trying to write in unallocated memory. This may be due to a failure in the malloc() of ultimo in Ubuntu, for example, since you do not check whether the allocation was successful. If it is not, ultimo will be NULL and the strcpy() will generate segmentation failure.

In any case, try to fix these problems so that your code becomes more robust, and then try again. If it doesn’t work, I suggest that you work with flag -g and try to run by gdb:

  • typhoon gdb meuexecutavel, after seeing the prompt typhoon run[enter] and your program will be running.
  • enter the input values to the point where the error occurs, when the prompt of gdb will appear again. Then you can type list to see the line where the error occurred and type print [variável] to see the value of any variable. At least one of them will be with an unexpected value, and from there you can determine more precisely what happened.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.