[英]strcpy works fine, even though memory is not allocated
即使我沒有為chr
分配任何內存,下面的c ++程序也能正常工作。 我經歷了谷歌,所以碰到了這個為什么為什么故意不正確使用strcpy不會可怕地失敗?
在此程序對於目標空間小於源空間的目標可以很好地工作。 在我的情況下, 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
正在寫入某個隨機內存位置。
C ++標准未定義程序的行為。
這意味着任何C ++實現(例如,編譯器)都可以執行所需的操作。 打印“你好!” 在stdout上將是可能的結果。 就涉及C ++標准而言,格式化硬盤仍然是可以接受的。 但是,實際上,堆上的一些隨機內存將被覆蓋,從而產生不可預測的后果。
請注意,程序甚至可以按預期方式運行。 目前。 除非是星期五。 或者直到您修改完全不相關的內容。 這就是您所遇到的情況,從程序員的角度來看,這是最糟糕的事情之一。
稍后,您可能會添加一些代碼並看到程序崩潰,並認為問題出在剛剛添加的代碼中。 這可能會導致您花費大量時間調試代碼的錯誤部分。 如果發生這種情況,歡迎下地獄。
因此,您永遠都不應依賴未定義的行為。
實際上, strcpy()
正在寫入隨機位置。
如果您的程序運行正常並且沒有崩潰,那將是一種不幸。
您已經在堆棧上的MyString
類的對象上創建了。 在該對象中,有一個成員指針chr
,它指向某個任意位置。 您的構造函數是否需要初始化該指針或為該指針指向分配內存? -不,不是。 因此, chr
指向某處。
反過來, strcpy()
並不關心指針的有效性,它相信您的專業知識可以提供有效的輸入。 因此,它確實完成了復制工作。 幸運的是,在未初始化的chr
指向的位置覆蓋內存不會使您的程序崩潰,但這只是“幸運的”。
實際上, 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;
}
這不會顯示任何錯誤,但是您可以通過我的示例理解這不是一個好習慣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.