簡體   English   中英

C ++內存訪問沖突

[英]c++ memory access violation

我正在學習C ++,目前的工作遇到很多麻煩。 到目前為止,我已經完成了很多工作。 但是,由於我認為我對幕后發生的事情知之甚少,所以我最近的進展非常緩慢。

我在以下代碼中嘗試做的是:

  • 獲得兩個單獨的值(子彈傷害)。 做完了
  • 創建一個動態數組。 做完了
  • 用一個值填充所述動態數組的一部分(即1到10之間的隨機數的模數的大小),其余部分以隨機順序填充。 我在這里遇到麻煩。
  • 清理所述動態數組使用的內存。 做完了

我得到的錯誤如下:

類3.exe中0x00a323e3的未處理異常:0xC0000005:訪問沖突讀取位置0xcdcdcdcd。

我很確定在嘗試將ammoArray[i]設置為值時會發生錯誤。 但是我不知道為什么給我,我的代碼可以很好地編譯。 我玩了一下,在一種情況下,我得到它來存儲bDamagesDamage的內存地址,然后打印出數組中每個元素的內存地址。 我想要做的是存儲bDamagesDamage持有的值。

現在我的問題是:

為什么ammoArray不存儲bDamagesDamage的值而不是數組元素的內存地址? 以及如何存儲它們?

這是我的Main.cpp:

#include <cstdlib>
#include "Ammunition.h"
#include "AmmunitionManager.h"
#include "Bullet.h"
#include "Game.h"
#include "Pistol.h"
#include "Player.h"
#include "Point.h"
#include "Shell.h"
#include "Shotgun.h"
#include "WeaponManager.h"
#include "Weapons.h"

using namespace std;

void main()
{
    Ammunition amVar;
    AmmunitionManager *var = new AmmunitionManager();

    amVar.setBDamage(6);
    amVar.setSDamage(2);
    var->FillAmmoArray(amVar.getSDamage(),amVar.getBDamage());

    system("PAUSE");
}

這是相關類的.h文件:

#ifndef AMMUNITIONMANAGER_H
#define AMMUNITIONMANAGER_H
#include "Point.h"
#include "Ammunition.h"

class AmmunitionManager
{
public:
    AmmunitionManager();
    AmmunitionManager(int,int);
    ~AmmunitionManager();

    void FillAmmoArray(int,int);
private:
    Ammunition Ammo;
    int **ammoArray;
};

#endif

這是相關類的.cpp文件:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include "AmmunitionManager.h"
#include "Point.h"
#include "Ammunition.h"

using namespace std;

AmmunitionManager::AmmunitionManager()
{
}


AmmunitionManager::AmmunitionManager(int sDamage,int bDamage)
    :Ammo(sDamage,bDamage)
{
    cout << "Filling ammo reservoir." << endl;
    ammoArray = new int* [10];
}

void AmmunitionManager::FillAmmoArray(int sDamage,int bDamage)
{
    srand(time(NULL));
    int *holdS = &sDamage;
    int *holdB = &bDamage;
    if(ammoArray)
    {
        for(int i = 0;i < 9;i++)
        {
            int randC = rand() % 2 + 1;
            if(randC == 1)
            {
                cout << "Was: " << ammoArray[i] << endl;//I am getting the error here.
                ammoArray[i] = holdS;
                cout << "Is: " << ammoArray[i] << endl;
            }
            if(randC == 2)
            {
                cout << "Was: " << ammoArray[i] << endl;//I am getting the error here.
                ammoArray[i] = holdB;
                cout << "Is: " << ammoArray[i] << endl;
            }
        }
    }
}

AmmunitionManager::~AmmunitionManager()
{
    *ammoArray = 0;
    if(ammoArray)
    {
        delete [] ammoArray;
    }
}

問題是您使用默認構造函數初始化AmmunitionManager

AmmunitionManager *var = new AmmunitionManager();

在默認構造函數中,您什么也不做,因此ammoArray可以包含任何值。 最好將所有數據初始化為其默認值:

AmmunitionManager::AmmunitionManager() : Ammo(), ammoArray(NULL/* or nullptr for C++11 */)
{
}

現在,如果您要求

var->FillAmmoArray(amVar.getSDamage(),amVar.getBDamage());

由於ammoArray為NULL,它將立即退出。 也許您還是想初始化ammoArray ,所以默認構造函數也應該具有其初始化:

AmmunitionManager::AmmunitionManager() : Ammo()
{
    ammoArray = new int* [10];
}

srand也只能調用一次,因此最好放置此代碼

srand(time(NULL));

main()或保證僅執行一次的任何其他模塊中。

在析構函數中,不需要為零*ammoArray=0 ,它實際上將0放置在該數組的第一個元素上(就是這樣),無論如何都將其刪除。 並假設ammoArray為NULL,訪問*ammoArray會導致另一個分段錯誤。

另外,也無需在刪除之前檢查ammoArray beibg NULL。 該標准允許“ delete ” NULL指針。 delete只會返回而不執行任何操作。

一般說明

最好使用(更安全,更容易維護) std::vector而不是(動態)數組和智能指針,而不是平面數組。

我沒有收到任何錯誤(VS2013)。 但是存儲的值是sDamage和bDamage的地址。

您是否正確使用AmmunitionManager(int sDamage,int bDamage)作為用於創建AmmunitionManager對象的構造函數? 從我所看到的,你不是。

除此之外,請問您為什么要使用諸如**ammoArray類的奇異構造而不是例如簡單的vector<int> 我猜這是您分配的一部分,但我只是想確保自己沒有遺漏任何東西。

我這樣稱呼對象:

int _tmain(int argc, _TCHAR* argv[])
{
    AmmunitionManager* tc = new AmmunitionManager(5,10);
    tc->FillAmmoArray(10,10);

    return 0;
}

為什么ammoArray不存儲bDamage和sDamage的值而不是數組元素的內存地址?

因為您說過應該存儲地址。
這是一個指向指針的指針:

int **ammoArray;

這是一個指針數組:

ammoArray = new int* [10];

以及如何存儲它們?

通過執行以下操作:

int *ammoArray;

和這個:

ammoArray = new int [10];

並相應地調整FillAmmoArray

默認構造函數應如下所示:

AmmunitionManager::AmmunitionManager()
  : ammoArray(nullptr)
{
}

析構函數應如下所示:

AmmunitionManager::~AmmunitionManager()
{
    delete [] ammoArray;
}

而且你只應該打電話給srand一次。
通常在main的開頭完成。

如果不進行構建和調試,回答起來會有些棘手,但是讓我印象深刻的第一件事是:為什么整個都使用int指針( * )?

為什么不只是將數組作為指針:

int *ammoArray;

並設置其他int -instances(刪除指針- *和( & )的address-of )?

問候

暫無
暫無

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

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