1

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, "");
}
4
  • 3
    @Luv: they are returning a string literal, that has static storage duration. Commented Dec 5, 2018 at 6:40
  • @Mat you are right. The problem seems to be the free here Commented Dec 5, 2018 at 6:45
  • WHat does the function return if n > 1 ? This is relevant. Commented Dec 5, 2018 at 6:49
  • @Jabberwocky It returns the correct answer (the expected strings in the Test function) . I pass those tests, its just the -1 test I fail but now I know this was due to the free statement. That's why that code is irrelevant Commented Dec 5, 2018 at 7:01

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

2

The fucntion sc() is returning a string constant "". String constants automatically allocated in a separate memory.

sc() is returning address of this string constant. In do test(), you are storing the address in actual variable and freeing it.

You are not suppose to free that memory. Just remove free(actual);.

Comments

2

The challenge seem to require that the function returns a dynamic allocated string. This can be seen from:

char* actual = sc(n);
...
free(actual);  // free is for dynamic allocated memory

Therefore the function must use a malloc type function to allocate the string. strdup does that, i.e. it allocates dynamic memory and makes a copy of the string (i.e. "" in this code) into that memory.

Just doing return ""; will return the address to a string (i.e. "") with static storage duration, i.e. some memory that can't be freed. Calling free on memory with static storage duration leads to undefined behavior which may be a program crash.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.