views:

127

answers:

2

I am trying to implement an eqivilent version of perl's chomp() function in C and I have come across a corner case where a string literal passed as the argument will cause a segmentation fault (rightfully so).

Example chomp("some literal string\n");

Is there a defined way in C99 to detect wether or not my function was passed a string literal so that I can return without attempting to NUL it out?

char* chomp(char *s)
{
    char *temp = s;

    if (s && *s)
    {
        s += strlen(s) - 1;
        if (*s == '\n')
        {
            *s = '\0';
        }
    }
    return temp;
}
+3  A: 

Your chomp should ideally create a new string and return it. There is no way to determine if you were passed a string literal or not. In fact, I'd suggest using the following signature for chomp:

char *chomp(const char *s); /* do not modify input parameters */

Or, you could create two different functions and document them for the clients: use chomp for non-literals and chompl for literal strings.

dirkgently
Is there a recommended practice other than documentation to alert the caller that this could be a potential memory leak if not `free()`'d?
SiegeX
Not exactly. How will you ever know when the client is through using this object? See `strdup` documentation for example.
dirkgently
+5  A: 

Is there a defined way in C99 to detect wether or not my function was passed a string literal so that I can return without attempting to NUL it out?

You shouldn't.

Your API shouldn't attempt to fudge things for the caller, only to have it break later on. If the caller breaks the rules, they should find out then and there.

If the caller passes a non-mutable string to a function that expects a mutable one, it should segfault. Anything else is bad design.

(Addendum: The best design, of course, would be to return a copy of the string that the caller is responsible for freeing.)

Anon.
Is there a recommended practice other than documentation to alert the caller that this could be a potential memory leak if not `free()`'d?
SiegeX
@SiegeX - one thing I like to do is include alloc in the names of functions that do that `char *chomp_alloc(const char *);`
R Samuel Klatchko
@SiegeX: I would go with `error_t chomp(const char* input, char** out_result)` myself. It's obvious there is something coming out of it that isn't there for syntax, so obviously you have to free it, and you also get a specific error.
Simon Buchan