kovac
kovac

Reputation: 5389

Why doesn't the strcat implementation cause a segmentation fault?

I'm trying to learn C and I tried the exercise in the book "The C Programming Language" in which I implemented the strcat() function as below:

char *my_strcat(char *s, const char *t)
{
    char *dest = s;

    while (*s) s++;
    while (*s++ = *t++);

    return dest;
}

And I'm calling this like:

int main(int argc, char const *argv[])
{
    char x[] = "Hello, ";
    char y[] = "World!\n";

    my_strcat(x, y);
    puts(x);

    return 0;
}

My problem is, I don't fully understand my own implementation.

My question is by the time line while (*s) s++; completes, now I have set the address held in s to the memory location that contains \0 which is the last element of array x.

Then in the line while (*s++ = *t++);, I'm setting s to the address of the next block of memory which is outside array x and copy the content of t to this new location. How is it allowed to write the content at the location of t to the location pointed by s when it was not part of the storage I had requested when I initialized x?

If I called my_strcat like below, I get a segmentation fault:

int main(int argc, char const *argv[])
{
    char *x = "Hello, ";
    char *y = "World!\n";

    my_strcat(x, y);
    puts(x);

    return 0;
}

which kind of makes sense. My understanding is char *x = "foo" and char x[] = "foo" are the same with the difference that in the latter case, storage allocated to x is fixed while the first is not. So, I feel like the segmentation fault should happen in the latter case, rather the former?

Thank you for clarification.

Upvotes: 2

Views: 58

Answers (1)

S.S. Anne
S.S. Anne

Reputation: 15576

This is undefined behavior. Anything can happen.

The real, practical reason that the first program works is because the strings in the first are stored on the stack. It overwrites the stack, which causes undefined behavior, but "just works", which is unfortunate.

The second program doesn't "work" because the strings are stored in read-only memory. Any attempt to write to these strings will cause undefined behavior (or a segfault).

Your implementation of strcat is valid, you just need to allocate adequate space for the string that you're trying to append to.

So, to recap:

How is it allowed to write the content at the location of t to the location pointed by s when it was not part of the storage I had requested when I initialized x?

It's not. This is undefined behavior that just happens to "work".

Upvotes: 6

Related Questions