在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
正在写入某个随机内存位置。
答案 0 :(得分:4)
C ++标准未定义程序的行为。
这意味着任何C ++实现(例如编译器)都可以做任何想做的事情。打印“你好!”在stdout将是一个可能的结果。考虑到C ++标准,格式化硬盘仍然是可以接受的。但实际上,堆上的一些随机内存将被覆盖,带来不可预测的后果。
请注意,程序甚至可以按预期运行。目前。除非它是星期五。或者直到你修改完全不相关的东西。这就是你的情况,从程序员的角度来看,这是最糟糕的事情之一。
稍后,您可能会添加一些代码并看到您的程序崩溃,并认为问题出在您刚刚添加的代码中。这可能会导致您花费很长时间来调试错误的代码部分。如果发生这种情况,欢迎来到地狱。
因此,您永远不应该依赖未定义的行为。
答案 1 :(得分:3)
strcpy()
确实在写一个随机位置。
如果您的程序运行良好并且没有任何崩溃,那就是一个盲目的运气。
您已在堆栈上创建MyString
类的对象。在该对象中有一个成员指针chr
,它指向某个任意位置。你的构造函数是否注意初始化该指针或为指针分配内存? - 不,它没有。所以chr
指向某处。
strcpy()
反过来并不关心任何指针有效性,它相信你的专业性提供有效的输入。所以它完成了复制蜇伤的工作。幸运的是,覆盖未初始化chr
指向的位置的内存不会导致程序崩溃,但这只是“幸运”。
答案 2 :(得分:2)
众所周知,strcpy()可能会导致溢出错误,因为无论数据是否适合新数组,都不会进行检查。 这种溢出的结果可能有时从未被注意到,这完全取决于数据的写入位置。但是,常见的结果是堆和/或程序损坏。
上详细了解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;
}
这不会显示任何错误,但您可以通过我的示例了解这不是一个好习惯。