strcpy works fine, even though memory is not allocated

308 views Asked by At

Below c++ program works fine, even though i have not allocated any memory to chr. I went through google, SO and came across this Why does this intentionally incorrect use of strcpy not fail horribly?

Here the program works fine for destination which has space less than the source. Does that apply in my case also,strcpy writes into a random location in the heap?

#include<iostream>
using namespace std;

class Mystring
{
    char *chr;
    int a;
    public:
    Mystring(){}
    Mystring(char *str,int i);
    void Display();

};

Mystring::Mystring(char *str, int i)
{
   strcpy(chr,str);
   a = i;
}

void Mystring::Display()
{
    cout<<chr<<endl;
    cout<<a<<endl;
}


int main()
{
    Mystring a("Hello world",10);
    a.Display();
    return 0;
}
output:-
Hello world
10

I tried the same thing with another c++ program, with any class and class member, and i was able to see the crash.

#include<iostream>
using namespace std;

int main()
{
    char *src = "Hello world";
    char *dst;
    strcpy(dst,src);
    cout<<dst<<endl;
    return 0;
}

Please help me understand the behavior in the first c++ program.Is memory allocated somehow or strcpy is writing to some random memory location.

4

There are 4 answers

0
Igor S.K. On

strcpy() is indeed writing to a random location.

And it's a blind luck if your program runs fine and nothing crashes.

You have created on object of MyString class on a stack. In that object there's a member pointer chr, which points to some arbitrary location. Does your constructor take care to initialize that pointer or allocate a memory for the pointer to point at? -- No, it doesn't. So chr points somewhere.

strcpy() in its turn doesn't care about any pointer validity, it trusts your professionalism to provide valid input. So it does its job copying stings. Luckily, overwriting memory at the location pointed by an uninitialized chr doesn't crash you program, but that's "luckily" only.

0
Milan Patel On

Actually, strcpy() does something like this:

char *strcpy(char *dest, const char *src)
{
  unsigned i;
  for (i=0; src[i] != '\0'; ++i)
    dest[i] = src[i];
  dest[i] = '\0';
  return dest;
}

So, when you pass a pointer to some character array to strcpy, it copies data from src to dest until it reaches NULL terminated character.
Character pointer does not contain any information about length of string, so when you pass dest pointer, it copies data even though you haven't assigned memory to it.

Run this example code, you will get my point:

#include <cstring>
#include <iostream>

using namespace std;

int main()
{
    char str1[] = "Hello_World!";
    char str2[5];
    char str3[10];
    strcpy(str2,str1);
    cout << "string 1:" << str1 << endl;
    cout << "string 2:" << str2 << endl;
    cout << "string 3:" << str3 << endl;
    return 0;
}

This will not show any error but you can understand by my example that this is not a good practice.

5
A B On

It is known that strcpy() can cause overflow errors, because there is no check made wherever the data will fit in the new array or not. The outcome of this overflow may sometime never been noticed, it all depends on where the data is written. However a common outcome is heap and/or program corruption.

A safe alternative of strcpy() is the usage of strcpy_s() that requires also the size of the array. You can read more about the usage of strcpy_s() on MSDN or here

4
chi On

The behavior of your program is undefined by the C++ standard.

This means that any C++ implementation (e.g. a compiler) can do whatever it wants. Printing "hello!" on stdout would be a possible outcome. Formatting the hard disk would still be acceptable, as far as the C++ standard is involved. Practically, though, some random memory on the heap will be overwritten, with unpredictable consequences.

Note that the program is even allowed to behave as expected. For now. Unless it's Friday. Or until you modify something completely unrelated. This is what happened in your case, and is one of the worst thing to happen from the point of view of a programmer.

Later on, you may add some code and see your program crash horribly, and think the problem lies in the code you just added. This can cause you to spend a long time debugging the wrong part of the code. If that ever happens, welcome to hell.

Because of this, you should never, ever, rely on undefined behavior.