strcpy工作正常,即使没有分配内存

时间:2015-06-24 11:10:30

标签: c++ memory constructor strcpy

在c ++程序下工作正常,即使我没有为chr分配任何内存。 我经历了谷歌,所以我遇到了这个问题 Why does this intentionally incorrect use of strcpy not fail horribly?

这里程序适用于空间小于源的目的地。 这也适用于我的情况,strcpy写入堆中的随机位置吗?

#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

我用另一个c ++程序尝试了同样的事情,任何类和类成员,我都能看到崩溃。

#include<iostream>
using namespace std;

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

请帮我理解第一个c ++程序中的行为。是以某种方式分配内存还是strcpy正在写入某个随机内存位置。

4 个答案:

答案 0 :(得分:4)

C ++标准未定义程序的行为。

这意味着任何C ++实现(例如编译器)都可以做任何想做的事情。打印“你好!”在stdout将是一个可能的结果。考虑到C ++标准,格式化硬盘仍然是可以接受的。但实际上,堆上的一些随机内存将被覆盖,带来不可预测的后果。

请注意,程序甚至可以按预期运行。目前。除非它是星期五。或者直到你修改完全不相关的东西。这就是你的情况,从程序员的角度来看,这是最糟糕的事情之一。

稍后,您可能会添加一些代码并看到您的程序崩溃,并认为问题出在您刚刚添加的代码中。这可能会导致您花费很长时间来调试错误的代码部分。如果发生这种情况,欢迎来到地狱。

因此,您永远不应该依赖未定义的行为。

答案 1 :(得分:3)

strcpy()确实在写一个随机位置。

如果您的程序运行良好并且没有任何崩溃,那就是一个盲目的运气。

您已在堆栈上创建MyString类的对象。在该对象中有一个成员指针chr,它指向某个任意位置。你的构造函数是否注意初始化该指针或为指针分配内存? - 不,它没有。所以chr指向某处。

strcpy()反过来并不关心任何指针有效性,它相信你的专业性提供有效的输入。所以它完成了复制蜇伤的工作。幸运的是,覆盖未初始化chr指向的位置的内存不会导致程序崩溃,但这只是“幸运”。

答案 2 :(得分:2)

众所周知,strcpy()可能会导致溢出错误,因为无论数据是否适合新数组,都不会进行检查。 这种溢出的结果可能有时从未被注意到,这完全取决于数据的写入位置。但是,常见的结果是堆和/或程序损坏。

strcpy()的一个安全替代方法是使用strcpy_s(),它也需要数组的大小。您可以在MSDNhere

上详细了解strcpy_s()的使用情况

答案 3 :(得分:0)

实际上,strcpy()做了类似的事情:

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;
}

因此,当您将指向某个字符数组的指针传递给strcpy时,它会将数据从src复制到dest,直到它到达NULL终止字符。
字符指针不包含任何有关字符串长度的信息,因此当您传递dest指针时,即使您没有为其分配内存,它也会复制数据。

运行此示例代码,您将得到我的观点:

#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;
}

这不会显示任何错误,但您可以通过我的示例了解这不是一个好习惯。