Search code examples
cstringfunctionreturn

Error when returning a string from a function


This is from a Codewars challenge so I'll leave out unnecessary code from this function. Basically if n <= 1, I need to return an empty string.

char* sc(int n)
{
    if(n > 1) {
        //irrelevant code
    }

    //return strdup("");
    return "";
}

If the value being passed is -1, when I use return ""; I get a "Test crashed" message but when I use return strdup(""); I pass the test. Just wondering why this is?

Edit: This is how the function is called. It is only the last test that fails.

#include <criterion/criterion.h>
#include <string.h>

char* sc(int);

void dotest(int n, const char* expect)
{
  char* actual = sc(n);
  cr_expect(!strcmp(actual, expect), "Expected: '%s', got: '%s'\n", expect, actual);
  free(actual);
}

Test(the_multiply_function, should_pass_all_the_tests_provided) {
    dotest(2,"Aa~ Pa! Aa!");
    dotest(6, "Aa~ Aa~ Aa~ Aa~ Aa~ Pa! Aa!");
    dotest(7, "Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Pa!");
    dotest(10, "Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Aa~ Pa!");
    dotest(1, "");
    dotest(-1, "");
}

Solution

  • For usage of free(), from C11, chapter §7.22.3.3 (emphasis mine)

    The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

    and, for strdup() (again emphasis mine)

    The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(), and can be freed with free().

    So, when you use return strdup("");, the pointer which is returned is eligible to be passed to free() - everything is alright.

    OTOH, by saying return "";, you're returning a pointer to the first element of a string literal which is not a suitable candidate to be passed to free(), as mentioned above, it invokes undefined behaviour.

    The crash or segmentation fault is one of the many side effects of UB.