Error Segmentation fault (core dumped)

8

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

  

Segmentation fault (core dumped)

Another thing is that when I performed the same operation as preenche on main , using ficha.name instead of dados , the system printed only the first letter.

Why is the string not printing in full? And why do I get the error when I use 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] = '
#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] = '%pre%';

    return (dados);

}

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

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

return 0;
}
'; return (dados); } int main(int argc, const char *argv[]) { ficha_t ficha; ficha.name = preenche(); printf("%s", ficha.name); return 0; }
    
asked by anonymous 01.03.2015 / 23:59

3 answers

5

There are several problems in your code.

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

The logic of your aloca function is wrong. Each time you run 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, with more characters.

Your function should use the command realloc , passing the correct size of the memory region to be allocated, which is the "length of the string + terminator of the string + 1", in order to store one more byte in it. In addition, there is no guarantee that the memory manager will not change the address pointed by ptr , so it is also necessary to change the signature of the command.

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 realloc command re-allocates 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 bad programming practice. In larger projects (or real projects), in addition to bad practice, it can cause unwanted problems in your and other applications running on the machine.

On the second part of your question, it is unclear what you mean. But this may solve the problem. Test, and update your question with more information so I can complete my answer.

NULL pointer vs realloc

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

  

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

As long as the implementations of realloc are correct (and usually are), you can rest easy!

I hope I have helped.

    
02.03.2015 / 00:25
3

The other answers have already shown that the code has some problems. I'll put how 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] = '
#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] = '%pre%';
    return dados;
}

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

See running on ideone .

I've tried to keep more or less the same structure as your code but it's not the best way to handle it. As you are probably learning and experiencing, you did not want to change your intention, but remember that you have better ways to achieve the same result. There is inefficiency in doing multiple reallocations. Especially this form is creating memory management problems. A restricted example will not cause problems, but at any point you are releasing the memory allocated to the name member. I imagine that you will then move on to the other members and the problem will increase.

    
02.03.2015 / 00:55
2

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

You pass this pointer to the function aloca() , but it does not change: in C all parameters are passed by value.

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

    
02.03.2015 / 00:27