I need explanation because the code in C gives a Segmentation fault error

0

I started my dynamic allocation studies but I can not make a simple example, I could not 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;
    }
}
    
asked by anonymous 16.06.2018 / 20:35

1 answer

1

I refigure in a way that works. Some changes I've made to stay in a cleaner, more standardized style, and meet the demands of a decent compiler with bound protections 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;
}

The problem is that you are not booting the way you want.

If you want to pass an argument by reference you have to use a reference to 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 must be passed by reference, so there should be a double pointer there and treat that pointer to tinker with the innermost pointer as I did in the code.

Of course this code is a bit confusing. It would probably be best to return the pointer instead of passing 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 you are exercising another concept. % Writing% in this form is nothing better than doing it without the function. Of course, it can be useful and have a reason. It is an abstraction in the future to be able to change how you create the point so that you do not have to change in the whole application. but there specifically does nothing useful.

The same can be said for criaPonto() . At the very least it could be one function. But this function has a problem other than that already reported, it allocates memory without being obvious that this occurs and hiding this fact it is easy to forget to deallocate, as it actually happened. This case is not a problem because the code ends thereafter and there are no consequences. But in a real code there will be and it will be harder to realize the error (there has already been 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 utility, and if it is to fill, then it should only 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;
}

But until the completion I'm not much of a fan of doing so, maybe even a macro was better, but not ideal.

    
16.06.2018 / 21:20