簡體   English   中英

對象周圍的堆棧已損壞

[英]stack around object was corrupted

我有以下代碼,運行后會拋出錯誤:

class arr2{
int count;
public:
    int elem[5];
    arr2()
    {
        count=-1;
        elem[5]=(0,0,0,0,0); //{} throws error i dont know why
    }
};
int main()
{
    arr2 obj;

    vector<int> vec;
    vec.assign(10,42);
    vector<int> ::iterator itr=vec.begin();
    for(;itr!=vec.end();++itr){
        cout<<*itr<<endl;       
    }

    return 0;
}

變量'obj'周圍的錯誤堆棧已損壞。

如果我刪除arr2 obj; 然后就可以了 類本身或ctor elem[5]=(0,0,0,0,0);的語句有什么問題嗎elem[5]=(0,0,0,0,0); 我試圖用{}在main中定義一個數組,它工作正常。 我不知道為什么在課堂上失敗。

int arr4[4]={1,2,3,4}; //OK
int elem[5]; // Represents that the array is of size 5 

由於數組索引以0開頭,因此可用的數組索引為:

  • elem[0]
  • elem[1]
  • elem[2]
  • elem[3]
  • elem[4]

(共五個要素)

elem[5]超出范圍。

分配

elem[5]=(0,0,0,0,0);

在數組的第六個位置寫入一個零(請閱讀有關逗號運算符的信息 )(請記住,數組索引是從零開始的),它是數組末尾的一個零。 超出數組范圍進行寫入會導致未定義的行為

有幾種初始化數組的方法,最簡單的方法是構造函數初始化列表:

class arr2
{
    int elem[5];

public:
    arr2()
        : elem{}
    {}
};

上面的代碼將對數組進行值初始化 ,這意味着數組中的每個元素也將被值初始化,對於int值初始化,會將其設置為0


為了擴展您遇到的錯誤,當今幾乎所有系統和編譯器都將局部變量存儲在堆棧中,該局部變量在main函數中包含變量obj 將對象放置在堆棧上還將其成員變量放置在堆棧上。 如果您寫出數組的邊界,那么您也將寫在您不擁有使用權的堆棧內存中,從而損壞堆棧。

您需要考慮這里有兩種不同的構造。

初始化

//                  initialiser
//                      |
//  name ("elem")       |
//      |               |
//     ▼▼▼▼    ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
   int elem[5] = {0, 0, 0, 0, 0};
// ▲▲▲     ▲▲▲
//   \      /
//    \    /
//     \  /
//  type (int[5])

分配

//         new element value
//                |
// name ("elem")  |
//     |          |
//    ▼▼▼▼      ▼▼▼▼▼
      elem[n] = 12345;
//        ▲▲▲ ▲
//         |  |
//         | assignment operator
//         |
//     index (n)

您的問題與以main還是以類定義編寫代碼無關。 問題是您正在嘗試編寫分配 ,就好像它是初始化一樣

  • 初始化程序{0, 0, 0, 0, 0}根本不能在分配中使用
  • 當您編寫elem[5]而不是int elem[5] ,您是在命名elem 6 元素,而不是聲明一個新的大小為5的數組elem

當您改用(0, 0, 0, 0, 0) 0,0,0,0,0)時,錯誤消失了,因為這是一個計算結果為0的表達式,您可以將0分配給int數組的元素。

不幸的是,您對一個不存在的元素執行此操作,因為elem[5]超出范圍。 它是五元素數組中假設的第六個元素。


一次無法使用初始化程序語法分配給數組的所有元素是C和C ++的局限性。

要在任意位置分配給數組,您必須在循環中一個接一個地分配它們,或使用fill函數:

std::fill(std::begin(elem), std::end(elem), 0);

…反正好多了。


幸運的是,您犯下了另一種實際上很方便的罪行:您實際上確實想初始化,即使此刻您正在構造器主體內進行賦值。 要初始化類成員,必須使用構造函數的member-initialiser列表 ,並且在發生這種情況時,構造函數的member-initialiser列表使我們能夠使用初始化語法:

arr2()
    : elem{0, 0, 0, 0, 0}
{}

…或更簡單地說:

arr2()
    : elem{}
{}

這不能達到您的期望:

elem[5]=(0,0,0,0,0);

您將索引5處的元素(超出范圍)的值指定為0。您沒有分配初始化程序列表,而是分配了一系列零,並且中間使用逗號(返回每個調用的第二個值),其中依次返回最右邊的零。

 elem[5]=(0,0,0,0,0); //{} throws error i dont know why

使用{}會引發錯誤,因為{}僅用於數組的初始化,而不能用於賦值。

同樣,上面的語句沒有將所有數組元素都分配為零,而是嘗試為elem [5]分配一個零,這實際上超出了數組的邊界。 您的數組以elem [0]開始,以elem [4]結尾。

elem [5]實際上是指下面定義的向量的地址。 向量vec;

當您破壞此內存時。 你有例外。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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