7

Take the following program:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char a[8] = "Hello, ";
    char b[7] = "world!";

    strcat(a, b);

    cout << a;

    return 0;
}

Notice that a and b have the same size as their assigned strings.

The documentation states that for strcat(a, b) to work, a needs to be large enough to contain the concatenated resulting string.

Nevertheless, cout << a displays "Hello, world!". Am I entering undefined behavior?

yngccc
  • 5,594
  • 2
  • 23
  • 33
wjmolina
  • 2,625
  • 2
  • 26
  • 35

5 Answers5

13

"Am I entering undefined behavior?"

Yes. A region at the end of a[] has been written over. It worked, this time, but might have belonged to something else.

Here I use a struct to control memory layout, and demonstrate it:

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    struct S {
        char a[8];
        char b[5];
        char c[7];
    };

    S s;
    strcpy( s.a , "Hello, " );
    strcpy( s.b , "Foo!" );
    strcpy( s.c , "world!" );


    strcat(s.a, s.c);

    cout << s.a << endl;
    cout << s.b << endl;

    cin.get();

    return 0;
}

This outputs:

Hello, world!
orld!

Instead of:

Hello, world!
Foo!

The strcat() has stomped all over b[].

Please note that in a real life example such bugs may be far more subtle, and lead you to wondering why perfectly innocent function calls 250 lines later crash and burn horribly. ;-)

EDIT: May I also recommend that you use strcat_s, instead? Or, even better, std::strings:

#include <string>
#include <iostream>

using namespace std;

int main()
{
    string a = "Hello, ";
    string b = "world!";
    a = a + b;
    cout << a;
}
Arkady
  • 358
  • 1
  • 2
  • 8
  • @Nawaz, what's a *good* question to you? Is it one that furthers *your* knowledge? Anyway... thanks, Arkady, for the non-narcissistic, thorough reply. – wjmolina Oct 07 '13 at 17:26
  • @JosuéMolina: Ask yourself this : what is a *not-so-good* question to you? – Nawaz Oct 07 '13 at 17:28
  • @Nawaz, I don't want to enter into a subjective argument with you. – wjmolina Oct 07 '13 at 17:28
  • @JosuéMolina: Great. Now you know it is *subjective*. :-) – Nawaz Oct 07 '13 at 17:29
  • @Nawaz, then keep it to yourself next time. – wjmolina Oct 07 '13 at 17:31
  • @JosuéMolina: Say that to yourself first. (Note that even though the question is not-so-good, I upvoted it, as a token of encouragement but reading your comments, it seems you like to be *praised* for everything you do.) – Nawaz Oct 07 '13 at 17:38
  • @Nawaz, I up-voted your reply because it is *edifying*; it made me a better C/C++ programmer. Nevertheless, your subsequent comment decried my inexperience. I want to learn and feel supported; if I sought praise, I would have more answers than questions on this site. – wjmolina Oct 07 '13 at 17:54
3

Am I entering undefined behavior?

Yes.


If the documentation says "a needs to be large enough to contain the concatenated resulting string", why don't you simply believe it? What is there to doubt?

Nawaz
  • 353,942
  • 115
  • 666
  • 851
2

In your program, array a is not large enough to contain the result. Therefore, your code is wrong and should be fixed. In the words of the standard, you are indeed entering undefined behavior, which means it may work or it may not...

nickie
  • 5,608
  • 2
  • 23
  • 37
  • It may work, for a bit. I've seen this bug run fine, until a call to std::vector::push_back() fails halfway through a loop in a totally different source file. Turns out exactly this kind of bug was the problem: part of the vector was being overwritten by the bad strcat(). – Arkady Oct 07 '13 at 17:07
2

strcat does what is says on the tin viz. copies b onto the end of a without any care as to what data is already there. Since both variables are on the stack one after the other things work. But try

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char a[8] = "Hello, ";
    int i =  10;
    char b[7] = "world!";

    strcat(a, b);

    cout << a << i;

return 0;
}

And you will probably get an unexpected result since your stack has been corrupted by strcat

doron
  • 27,972
  • 12
  • 65
  • 103
1

That is correct.... The behavior is undefined. Just because you got that answer does not mean that it will not crash next time since the array a is too small.

Jim
  • 1,056
  • 1
  • 13
  • 19