C ++内存访问冲突
c++ memory access violation
我正在学习 C++,但我在当前作业中遇到了很多麻烦。到目前为止,我已经完成了很多。然而,由于我认为我对幕后发生的事情了解不多,我最近的进展非常缓慢。
我在下面的代码中试图做的是:
- 获得两个独立的值(子弹伤害)。完成。
- 创建一个动态数组。完成。
- 用一个值填充所述动态数组的一部分(即1到10之间的随机数的模数的大小),其余部分以随机顺序填充另一个值。我在这里遇到了麻烦。
- 清理该动态数组占用的内存。完成。
我得到的错误如下:
Unhandled exception at 0x00a323e3 in Class 3.exe: 0xC0000005: Access
violation reading location 0xcdcdcdcd.
我很确定当我尝试将 ammoArray[i]
设置为一个值时会发生错误。但我不知道为什么它会给我,我的代码编译得很好。我玩了一下,在一个案例中,我用它来存储 bDamage
和 sDamage
的内存地址,然后打印出数组中每个元素的内存地址。我想要它做的是存储 bDamage
和 sDamage
.
持有的值
现在我的问题是:
为什么 ammoArray
不存储 bDamage
和 sDamage
的值,而是存储数组元素的内存地址?以及如何获取它来存储它们?
这是我的 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
.
开始时完成
我正在学习 C++,但我在当前作业中遇到了很多麻烦。到目前为止,我已经完成了很多。然而,由于我认为我对幕后发生的事情了解不多,我最近的进展非常缓慢。
我在下面的代码中试图做的是:
- 获得两个独立的值(子弹伤害)。完成。
- 创建一个动态数组。完成。
- 用一个值填充所述动态数组的一部分(即1到10之间的随机数的模数的大小),其余部分以随机顺序填充另一个值。我在这里遇到了麻烦。
- 清理该动态数组占用的内存。完成。
我得到的错误如下:
Unhandled exception at 0x00a323e3 in Class 3.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
我很确定当我尝试将 ammoArray[i]
设置为一个值时会发生错误。但我不知道为什么它会给我,我的代码编译得很好。我玩了一下,在一个案例中,我用它来存储 bDamage
和 sDamage
的内存地址,然后打印出数组中每个元素的内存地址。我想要它做的是存储 bDamage
和 sDamage
.
现在我的问题是:
为什么 ammoArray
不存储 bDamage
和 sDamage
的值,而是存储数组元素的内存地址?以及如何获取它来存储它们?
这是我的 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
.