Search code examples
cpointersundefined-behaviorlocal-variables

c program doesn't give me errors


Consider the following program

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


typedef struct my_string{
    int len;
    char *buf;
} my_string_t;


my_string_t *init_my_string(char *);
my_string_t *call_init_my_string();

int main(int argc, char *argv[])
{
     my_string_t *st1 = call_init_my_string();

     printf("%d\n", st1->len);
     printf("%s\n", st1->buf);

     free(st1);

    return 0;
}


my_string_t *call_init_my_string()
{
    my_string_t *st1 = init_my_string("Foo");
    return st1;
}


my_string_t *init_my_string(char *s)
{
    my_string_t *st = (my_string_t *) malloc(sizeof(*st));
    st->len = strlen(s);
    st->buf = s;
    return st;
}

The question is, does this program suppose to result in undefined behaviour or some kind of error? since the string "Foo" inside function call_init_my_string is locally declared and get passed to init_my_string function. In init_my_string function, I allocate a space to hold the size of of the string and the string itself, but as i know, this allocation my_string_t *st = (my_string_t *) malloc(sizeof(*st)); only allocate enough space for st->len and st->buf pointer and not for string "Foo" since I only assign the string to st->buf instead of allocating it first and then do like the following:

 st->buf = (char *) malloc(strlen(s) + 1);
 memcpy(st->buf, s, strlen(s));
 st->buf[strlen(s)] ='\0';

But after I compile it and run, it gives me no errors and the program runs fine. why this program works fine and gives me no errors?

this is the result printed on the screen:

$ gcc struct_ptr_string1.c -o struct_ptr_string1
$ ./struct_ptr_string1

3
Foo

Solution

  • There's no undefined behaviour in your code.

    The string literal "Foo" has static storage duration. You are passing its address to init_my_string and simply store that address (essentially a pointer to "Foo").

    Your code is equivalent to (except we have one more copy of "Foo"):

    my_string_t *call_init_my_string()
    {
        static char s[] = "Foo";
        my_string_t *st1 = init_my_string(&s[0]);
        return st1;
    }
    
    my_string_t *init_my_string(char *s)
    {
        my_string_t *st = malloc(sizeof(*st));
        st->len = strlen(s);
        st->buf = s;
        return st;
    }