test * sample_function ()
{
test *abc;
strcpy(abc->name,"Surya");
What do you think abc
points to, here? The answer is, it doesn't really point to anything. You need to initialize it to something, which in this case means allocating some memory.
So, let's fix that first issue:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
strcpy(abc->name,"Surya");
Now, abc
points to something, and we can store stuff in there!
But ... abc->name
is a pointer too, and what do you think that points to? Again, it doesn't really point to anything, and you certainly can't assume it points somewhere you can store your string.
So, let's fix your second issue:
test * sample_function ()
{
test *abc = malloc(sizeof(*abc));
abc->name = strdup("Surya");
/* ... the rest is ok ... */
return abc;
}
Now, there's one last issue: you never release the memory you just allocated (this probably isn't an issue here, but it'd be a bug in a full-sized program).
So, at the end of main, you should have something like
free(abc->name);
free(abc);
return 1;
}
The final issue is a design one: you have three pointers in your structure, and only convention to help you remember which is dynamically allocated (and must be freed) and which point to string literals (and must not be freed).
That's fine, so long as this convention is followed everywhere. As soon as you dynamically allocate class
or rollno
, you have a memory leak. As soon as you point name
at a string literal, you'll have a crash and/or heap damage.
As japreiss points out in a comment, a good way to enforce your convention is to write dedicated functions, like:
void initialize_test(test *obj, const char *name, char *class, char *rollno) {
obj->name = strdup(name);
...
}
void destroy_test(test *obj) {
free(obj->name);
}
test *malloc_test(const char *name, ...) {
test *obj = malloc(sizeof(*obj));
initialize_test(obj, name, ...);
return test;
}
void free_test(test *obj) {
destroy_test(obj);
free(obj);
}