C ++内存访问冲突

c++ memory access violation

我正在学习 C++,但我在当前作业中遇到了很多麻烦。到目前为止,我已经完成了很多。然而,由于我认为我对幕后发生的事情了解不多,我最近的进展非常缓慢。

我在下面的代码中试图做的是:

我得到的错误如下:

Unhandled exception at 0x00a323e3 in Class 3.exe: 0xC0000005: Access violation reading location 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");
}

这是有问题的 class 的 .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

这是有问题的 class 的 .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;
    }
}

如果不构建和调试,回答起来有点棘手,但让我印象深刻的第一件事是:你为什么在整个过程中使用指向 int 的指针 (*)?

为什么不直接将数组作为指针:

int *ammoArray;

并创建其他 int 实例(删除指针 - *address-of 的(&))?

此致

问题是您使用默认构造函数初始化 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 只会 return 什么都不做。

一般说明

最好用(更安全,更容易维护)std::vector instead of (dynamic) arrays and smart pointers而不是扁平的

我没有收到任何错误 (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;
}

Why won't ammoArray store the values of bDamage and sDamage instead of the memory addresses of the array's elements?

因为你说它应该存储地址。
这是一个指向指针的指针:

int **ammoArray;

这是一个指针数组:

ammoArray = new int* [10];

And How do I get it to store them?

改为这样做:

int *ammoArray;

还有这个:

ammoArray = new int [10];

并相应地调整 FillAmmoArray

默认构造函数应如下所示:

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

析构函数应如下所示:

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

而且你应该只调用 srand 一次。
通常在main.

开始时完成