Reputation: 363
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
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
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
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
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
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