Error Segmentation fault (core dumped)

Asked

Viewed 42,472 times

10

I’m getting the following error message in my code:

Segmentation fault (core dumped)

Another thing is, when I performed the same function operation preenche in the main, using ficha.name in place of dados, the system printed only the first letter.

Why is the string not printed whole? And why do I get the error when using the function?

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

typedef struct{

    char *name;
    char *phone;
    char *city;
    char *state;

}ficha_t;

void aloca (char *ptr){

    ptr = (char*) calloc (1, sizeof(char));

    if(ptr == NULL){

            puts("** Memória Insuficiênte **");
            exit(0);

    }
}

char *preenche (){

    char *dados;
    int i = 0;

    do{
        aloca(dados);
        dados[i] = getchar();
        i++;

    }while(dados[i] == '\n');

    dados[i] = '\0';

    return (dados);

}

int main(int argc, const char *argv[])
{
ficha_t ficha;

ficha.name = preenche();
printf("%s", ficha.name);

return 0;
}

3 answers

4


There are several problems in your code.

Seg fault occurs because you are allocating insufficient memory for your variable and access unallocated memory regions.

The logic of its function aloca wrong. Every time you execute ptr = (char*) calloc (1, sizeof(char));, a single byte is allocated and its address is stored in ptr, and what you need, in the context of its use, is to expand the allocated memory, containing more characters.

Your function should use the command realloc, passing the correct size of the memory region to be allocated, which is the "string size + string terminator + 1", to store one more byte in it. Also, nothing guarantees that the memory manager will not change the address pointed by ptr, and you also need to change the command signature.

void aloca(char **ptr) {
    *ptr = (char*)realloc(*ptr, sizeof(char) * strlen(*ptr) + 2);
    if ( *ptr == NULL ) {
        puts("** Memória Insuficiênte **");
        exit(0);
    }
}

Note that this command is only used to allocate memory for strings.

The command realloc re-allocate memory by copying the old values to the new allocated region.

Note that in your code, you do not release memory at any time, which is a bad programming practice. In larger projects (or actual projects), in addition to bad practice, it can cause unwanted problems in your and other applications running on the machine.

About the second part of your question, it is not clear what you mean. But it might solve the problem. Test, and update your question with more information, so I can complete my answer.

NULL vs Pointer realloc

According to the man page, a call to realloc pointer NULL is equivalent to a call to malloc:

If ptr is NULL, then the call is equivalent to malloc(size), for all values of size;

Therefore, provided that the implementations of the realloc are correct (and usually are), can rest assured!

I hope I’ve helped.

3

The other answers already showed that the code has some problems. I will put as the code can be changed to work. It’s not the only way to do it, just one of them:

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

typedef struct {
    char *name;
    char *phone;
    char *city;
    char *state;
} ficha_t;

void aloca(char **ptr, int tamanho) {
    *ptr = (char *)realloc(*ptr, tamanho + 1);
    if(ptr == NULL){
        puts("** Memória Insuficiente **");
        exit(0);
    }
}

char *preenche() {
    char *dados = NULL;
    int i = 0;
    do {
        aloca(&dados, i);
        dados[i++] = getchar();
    } while (dados[i - 1] != '\n');
    dados[i - 1] = '\0';
    return dados;
}

int main(int argc, const char *argv[]) {
    ficha_t ficha;
    ficha.name = preenche();
    printf("%s", ficha.name);
    return 0;
}

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

I’ve tried to maintain more or less the same structure as your code, but it’s not the best way to deal with it. As you are probably learning and experiencing did not want to change your intention, but remember that there are better ways to get the same result. There is inefficiency in making multiple relocations. Especially this way is creating memory management problems. In a restricted example it will not cause problems but no time you are releasing memory allocated to the member name. I imagine that later you will touch the other members and the problem will increase.

  • 1

    Why the function aloca works, even without any return value? It’s some peculiarity of C that I don’t know?

  • @mgibsonbr Good question. This was unintentionally. But actually I’m investigating something related. I had to do something to make it work and I didn’t quite understand why. With the void didn’t work. But now it’s returning what? If I reach some conclusion I put.

  • 1

    According to that question on Soen, it will compile and execute without error if you omit the return statement, but what is actually returned is what is "left" in the return register. I believe that - as just before you called realloc, that returned a pointer, that pointer is still in the recorder, and so it is returned. What luck, huh? P

  • 1

    @mgibsonbr solved the problem and I was able to understand why I needed to return. The error of the original code made me look at the wrong thing. Of course I have to return something, I am passing the address and I want to receive the address, I am not passing the address p/ manipulate your content, as in other functions would be normal. This function is memory management. Of course it has to pass a pointer to the address and Vinicius had already done so and I had not realized.

2

In function preenche() the variable dados 'is an initialized pointer.

Pass that pointer to the function aloca(), but it is not changed: in C all parameters are passed by value.

Next you want to use the uninitialized pointer to enter the value. What’s invalid!

Browser other questions tagged

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