I need an explanation why the C code gives a Segmentation fault error

Asked

Viewed 110 times

0

I started my dynamic allocation studies but I’m not able to make a simple example, I couldn’t find the problem.

#include <stdio.h>
#include <stdlib.h>

#define SUCESSO 1
#define FALHA -1

typedef struct {
    int x;
    int y;
} Ponto;

void criarPonto(Ponto *ponto);
int preencherPonto(Ponto *ponto, int x, int y);

int main() {
    Ponto *ponto;
    criarPonto(ponto);
    printf("O endereco de memoria é: %d\n", ponto);
    preencherPonto(ponto, 0, 1);
    printf("Coordenada X: %d\n", (*ponto).x);
    printf("Coordenada Y: %d\n", (*ponto).y);
    return 0;
}

void criarPonto(Ponto * ponto) {
    ponto = (Ponto *) NULL;
}

int preencherPonto(Ponto *ponto, int x, int y) {
    Ponto *p;
    p = malloc(sizeof(Ponto));
    if(p == NULL) {
        return FALHA;
    } else {
        p->x = x;
        p->y = y;
        ponto = p;
    }
}
  • At first, criarPonto() is of no use. preenchePonto does not fill the ponto of main. If you want to check, just comment on both printfs after preencherPonto(ponto, 0, 1);, in main.

1 answer

1


I remade it in a way that works. Some changes I made to stay in a cleaner, more standardized style, and meet the demand for a decent compiler with protections linked to avoid inadvertent errors:

#include <stdio.h>
#include <stdlib.h>

#define SUCESSO 0
#define FALHA -1

typedef struct {
    int x;
    int y;
} Ponto;

void criarPonto(Ponto **ponto) {
    (*ponto) = (Ponto *)NULL;
}

int preencherPonto(Ponto **ponto, int x, int y) {
    *ponto = malloc(sizeof(Ponto));
    if (*ponto == NULL) return FALHA;
    (*ponto)->x = x;
    (*ponto)->y = y;
    return SUCESSO;
}
int main() {
    Ponto *ponto;
    criarPonto(&ponto);
    printf("O endereco de memoria é: %p\n", (void *)ponto);
    if (preencherPonto(&ponto, 0, 1) == FALHA) return FALHA;
    printf("O endereco de memoria é: %p\n", (void *)ponto);
    printf("Coordenada X: %d\n", ponto->x);
    printf("Coordenada Y: %d\n", ponto->y);
    return SUCESSO;
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

The problem is you’re not getting started the way you want.

If you want to pass an argument by reference you have to use a reference for it. If you want to change the value by reference it works. If the value you want to change is the reference then the reference should be passed by reference, so there should be a double pointer there and treat that pointer to move the innermost pointer, as I did in the code.

Of course this code is a bit confusing. It would probably be better to return the pointer instead of going to the reference. In general the pointer has been initialized or no longer serves as an error code.

The code created has little general use, unless it is exercising another concept. The criaPonto() written in this form is nothing better than doing straight without the function. Of course, it can be useful and have a reason. It’s an abstraction for the future to be able to change how you create the point in a way that doesn’t need to change in the whole application. but there specifically does nothing useful.

The same can be said for the preenchePOnto(). At the very least, it could be one function. But this function has another problem besides the one already reported, it allocates memory without being obvious that this occurs and hiding this fact makes it easy to forget to dislocate, as actually occurred. This case is not a problem because the code ends immediately and there are no consequences. But in a real code there will be and it will be more difficult to perceive the error (there was already one in a simple code, imagine in a complex).

It would be nice if C had a better syntax for initializing members of a dynamically allocated structure, but this function has little usefulness, and if it is to fill in, then it should just do this, not allocate. It may be that the allocation is in the creative function.

It gets better:

#include <stdio.h>
#include <stdlib.h>

#define SUCESSO 0
#define FALHA -1

typedef struct {
    int x;
    int y;
} Ponto;

void preencherPonto(Ponto *ponto, int x, int y) {
    ponto->x = x;
    ponto->y = y;
}
int main() {
    Ponto *ponto = malloc(sizeof(Ponto));
    if (ponto == NULL) return FALHA;
    preencherPonto(ponto, 0, 1);
    printf("O endereco de memoria é: %p\n", (void *)ponto);
    printf("Coordenada X: %d\n", ponto->x);
    printf("Coordenada Y: %d\n", ponto->y);
    free(ponto);
    return SUCESSO;
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

But until filling I’m not a fan of doing so, maybe even a macro would be better, but not ideal.

  • It was enlightening, I’m really training the concept, for some computer programming classes. Thanks for the reply.

  • Your code was above average than it appears here.

Browser other questions tagged

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