Knupel
Knupel

Reputation: 363

why a pointer char cause a segmentation fault in a struct environment

I"m a begginer in C, usually I used C++. I try to work whith a struct with a char array in it, but when I used an other char *str it raises a segfault.

My code:

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

typedef struct s_obj t_obj;

struct s_obj {
    char *str;
};

int main() {

    char *str; // if disable no segmentation fault
    t_obj obj; 
    printf("%lu\n",strlen(obj.str));
    return(0);
}

I tried to understand what you mean by "the argument of strlen must be a string" @anastaciu... so I tried to make a code to do that, but the result is the same: segfault when an other char *str is used.

I can't find a way to init my char *str in the struct.

typedef struct s_obj t_obj;
struct s_obj {
    char *str;
};

int main() {
    char *str; // if disable no segmentation fault fault
    t_obj obj;
    obj.str = strcpy(obj.str, "truc");
    // printf("%lu\n",strlen(obj.str));
    printf("%s\n",obj.str);
    return(0);
}

Upvotes: 1

Views: 830

Answers (4)

anastaciu
anastaciu

Reputation: 23832

The line

printf("%lu\n", strlen(obj.str));

Invokes undefined behavior, the argument of strlen must be a string, aka a null terminated char array, obj.str is not a string it is just an uninitialized pointer, you'll need to allocate memory for it or othewise make it point to a valid memory location.

For example:

t_obj obj;
obj.str = calloc(100, sizeof *obj.str); //99 character string, 0 initialized 
                                        //malloc does not "clear" the allocated memory
                                        //if you use it you can't use strlen before strcpy
printf("%zu\n",strlen(obj.str)); //will print 0, the string is empty
obj.str = strcpy(obj.str, "truc");
printf("%zu\n",strlen(obj.str)); //will print 4, the length of the string

Live demo

Tha fact that the program does not behave as badly when you remove char *str; is a matter that's well within the scope of undefined behavior:

Upvotes: 1

hiddenAlpha
hiddenAlpha

Reputation: 400

C is not C++ ;) Seems you've missed an important difference regarding the two.

C++ Example:

#include <string>
struct t_obj {
    std::string str;
};
void foo(){
    t_obj obj; // <-- In C++ this is enough to get a properly initialized instance.
}

In C++, this code will give you a properly initialized object with an (also initialized) string.

But in C (as in your sample):

typedef  struct t_obj  t_obj;
struct t_obj {
    char *str;
};
void foo(){
    t_obj obj; // <-- Nothing gets initialized here.
}

There is no initialization as in the C++ example above. obj will simply be a chunk of (not initialized) memory. You have to initialize it yourself.

There's also a Problem with your 2nd sample:

strcpy does not work that way. We need to pass an allocated chunk of memory to strcpy and it will copy data to that place we gave to it.

But as we pass a "not initialzed pointer", strcpy will try to write our data somewhere in memory.

I think question "whats the difference between C strings and C++ strings?" might be helpful. It explains some details about the difference of C and C++ strings.

Upvotes: 1

Knupel
Knupel

Reputation: 363

now the code work fine like that:

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

typedef struct s_obj t_obj;
struct s_obj {
    char *str;
};

int main() {
    char *str;
    t_obj obj;
    if (!(obj.str = (char*)malloc(sizeof(char))))
        return (0);
    obj.str = strcpy(obj.str, "truc");
    printf("%s\n",obj.str);
    free(obj.str);
    return(0);
}

Upvotes: -1

Sourav Ghosh
Sourav Ghosh

Reputation: 134396

In either case, you are using obj.str uninitialised.

The address it holds in indeterminate, and the content of the memory location it points to also indeterminate. So, it's not null-terminated, and using it with strlen() (i.e., with the functions which expects a string argument), will cause out of bound access, which is essentially invalid memory access, which in turn invokes undefined behaviour.

For reference, C11, chapter 7.24, String handling <string.h>

[...]Unless explicitly stated otherwise in the description of a particular function in this subclause, pointer arguments on such a call shall still have valid values,[...]

At least, initialize the pointers to a null-value.

Upvotes: 0

Related Questions