簡體   English   中英

即使未分配內存,strcpy也能正常工作

[英]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()可能導致溢出錯誤,因為無論數據是否適合新數組,都不會進行檢查。 這種溢出的結果有時可能從未引起注意,這完全取決於數據的寫入位置。 但是,常見的結果是堆和/或程序損壞。

strcpy()的安全替代方法是使用strcpy_s(),這也需要數組的大小。 您可以在MSDN此處閱讀有關strcpy_s()用法的更多信息。

實際上, 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM