c ++内存访问冲突

时间:2015-10-07 05:43:40

标签: c++ class access-violation

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

我在以下代码中尝试做的是:

  • 获取两个单独的值(子弹伤害)。完成。
  • 创建动态数组。完成。
  • 用一个值填充所述动态数组的一部分(即1到10之间随机数的模数的大小),其余部分以随机顺序填充。我在这里遇到了麻烦。
  • 清理所述动态阵列使用的内存。完成。

我得到的错误如下:

  

Class 3.exe中0x00a323e3处的未处理异常:0xC0000005:Access   违规阅读地点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;
    }
}

4 个答案:

答案 0 :(得分:0)

问题是您使用默认构造函数初始化v2b

AmmunitionManager

在默认构造函数中,您不执行任何操作,因此AmmunitionManager *var = new AmmunitionManager(); 可能包含任何值。 最好将所有数据初始化为默认值:

ammoArray

现在,如果你要求

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

它将立即退出,因为var->FillAmmoArray(amVar.getSDamage(),amVar.getBDamage()); 为NULL。 或者你可能想要初始化ammoArray,所以默认构造函数也应该初始化:

ammoArray

同样AmmunitionManager::AmmunitionManager() : Ammo() { ammoArray = new int* [10]; } 只应调用一次,因此最好放置此代码

srand

srand(time(NULL)); 或任何其他保证只执行一次的模块中。

在析构函数中,没有必要将main()置零,它实际上将0放在该数组的第一个元素上(并且它就是它),你仍然删除它。并且假设*ammoArray=0为NULL,访问ammoArray会导致另一个分段错误。

在删除之前,无需检查*ammoArray beibg NULL。该标准允许ammoArray&#39; NULL指针。 delete只会在没有做任何事情的情况下返回。

一般说明

最好使用(更安全,更易于维护)std::vector代替(动态)数组和smart pointers代替扁平数组。

答案 1 :(得分:0)

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

答案 2 :(得分: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的开头完成。

答案 3 :(得分:-1)

在没有构建和调试的情况下回答有点棘手,但首先让我感到惊讶的是:为什么你在整个过程中使用指针(*)到int

为什么不把数组作为指针:

int *ammoArray;

并制作其他int - 个实例(删除指针 - *address-of'(&))?

此致