读取位置 0xcdcdcdcd 时出现访问冲突。 C++

发布于 2024-10-29 20:40:30 字数 3149 浏览 2 评论 0原文

本质上我现在想做的是构建一个程序,允许您从 3 个不同的类别(坦克、近战、远程)中进行选择,当您选择类别时,您可以为其指定一个不超过 20 个字符的名称。选择 5 个职业并为每个冠军命名后,它会打印出您选择的每个职业的名称和健康状况。代码是这样的:

#include "Driver.h"
#include <stdio.h> 
#include "Mele.h"
#include "Ranged.h"
#include "Tank.h"

int main(void)
{

Champion *champ[5];
int i, choice;

printf("Enter the number for which class you would like to add to your team\n");
for(i = 0; i <= 4; i++)
{
    char name[20];
    //printf("Enter the number for which class you would like to add to your team");
    printf("1 = Tank\n");
    printf("2 = Ranged\n");
    printf("3 = Mele\n");
    scanf_s("%d", &choice);
    if(choice == 1)
    {
        printf("Give him a name!\n");
        scanf("%s", name);
        champ[i] = new Tank(name);
    }
    else if(choice == 2){
        printf("Give him a name!\n");
        scanf("%s", name);
        champ[i] = new Ranged(name);
    }
    else if(choice == 3){
        printf("Give him a name!\n");
        scanf("%s", name);
        champ[i] = new Mele(name);
    }
    else
    {
        printf("You did not enter a number between 1 and 3 please try again!\n");
        i = i - 1;
    }
}
for(i = 0; i <= 4; i++)
{
    printf("%s has %f health", champ[i]->getName(), champ[i]->getHealth());
}
return 0;
}

这是主要功能

冠军类看起来像:

Champion::Champion(void)
{
}
Champion::Champion(char name1[])
{ 
    name = name1;
}

char* Champion::getName(void)
{   
    return name;
}   

double Champion::getHealth(void)
{
    return health;
}

int Champion::getFluid(void)
{
    return fluid;
}

double Champion::getArmor(void)
{
    return armor;
}

double Champion::getSpecialA(void)
{
    return specialA;
}

double Champion::getDamage(void)
{
    return physDamage;
}

void Champion::setHealth(double health1)
{
    health = health1;
}
void Champion::setFluid(int fluid1)
{
    fluid = fluid1;
} 
void Champion::setArmor(double armor1)
{
    armor = armor1;
}
void Champion::getSpecialA(double specialA1)
{
    specialA = specialA1;
}
void Champion::setDamage(double physDamage1)
{
    physDamage = physDamage1;
}

然后我有 4 个其他类,分别称为 Tank、Ranged 和 Mele;所有这些都继承自 Champion 并且具有与 Champion 相同的设置。当我运行该程序时,我得到以下信息:

'dragons_rage.exe': Loaded 'C:\Users\Tom\Documents\Visual Studio 2010\Projects\dragons_rage\Debug\dragons_rage.exe', Symbols loaded.
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', Cannot find or open the PDB file
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', Cannot find or open the PDB file
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\KernelBase.dll', Cannot find or open the PDB file
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\msvcr100d.dll', Symbols loaded.
First-chance exception at 0x5dfc14cf (msvcr100d.dll) in dragons_rage.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
Unhandled exception at 0x5dfc14cf (msvcr100d.dll) in dragons_rage.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
The program '[516] dragons_rage.exe: Native' has exited with code -1073741819 (0xc0000005).

我不太确定这些错误是什么以及它们的含义,如果我能得到一些帮助,那就太棒了,谢谢!

Essentially what I'm trying to do at this point is build a program to allow you to pick from 3 different classes (Tank, Mele, Ranged) when you pick the class you would then give it a name of 20 or fewer chars. After picking 5 classes and giving each champ a name it would print out the name and health of each class you picked. code stands like this:

#include "Driver.h"
#include <stdio.h> 
#include "Mele.h"
#include "Ranged.h"
#include "Tank.h"

int main(void)
{

Champion *champ[5];
int i, choice;

printf("Enter the number for which class you would like to add to your team\n");
for(i = 0; i <= 4; i++)
{
    char name[20];
    //printf("Enter the number for which class you would like to add to your team");
    printf("1 = Tank\n");
    printf("2 = Ranged\n");
    printf("3 = Mele\n");
    scanf_s("%d", &choice);
    if(choice == 1)
    {
        printf("Give him a name!\n");
        scanf("%s", name);
        champ[i] = new Tank(name);
    }
    else if(choice == 2){
        printf("Give him a name!\n");
        scanf("%s", name);
        champ[i] = new Ranged(name);
    }
    else if(choice == 3){
        printf("Give him a name!\n");
        scanf("%s", name);
        champ[i] = new Mele(name);
    }
    else
    {
        printf("You did not enter a number between 1 and 3 please try again!\n");
        i = i - 1;
    }
}
for(i = 0; i <= 4; i++)
{
    printf("%s has %f health", champ[i]->getName(), champ[i]->getHealth());
}
return 0;
}

That's the main function

The champion class looks like:

Champion::Champion(void)
{
}
Champion::Champion(char name1[])
{ 
    name = name1;
}

char* Champion::getName(void)
{   
    return name;
}   

double Champion::getHealth(void)
{
    return health;
}

int Champion::getFluid(void)
{
    return fluid;
}

double Champion::getArmor(void)
{
    return armor;
}

double Champion::getSpecialA(void)
{
    return specialA;
}

double Champion::getDamage(void)
{
    return physDamage;
}

void Champion::setHealth(double health1)
{
    health = health1;
}
void Champion::setFluid(int fluid1)
{
    fluid = fluid1;
} 
void Champion::setArmor(double armor1)
{
    armor = armor1;
}
void Champion::getSpecialA(double specialA1)
{
    specialA = specialA1;
}
void Champion::setDamage(double physDamage1)
{
    physDamage = physDamage1;
}

Then i have 4 other classes called Tank, Ranged and Mele; all of these inherit from Champion and have the same set up as Champion. when i run the program i get this:

'dragons_rage.exe': Loaded 'C:\Users\Tom\Documents\Visual Studio 2010\Projects\dragons_rage\Debug\dragons_rage.exe', Symbols loaded.
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', Cannot find or open the PDB file
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', Cannot find or open the PDB file
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\KernelBase.dll', Cannot find or open the PDB file
'dragons_rage.exe': Loaded 'C:\Windows\SysWOW64\msvcr100d.dll', Symbols loaded.
First-chance exception at 0x5dfc14cf (msvcr100d.dll) in dragons_rage.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
Unhandled exception at 0x5dfc14cf (msvcr100d.dll) in dragons_rage.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
The program '[516] dragons_rage.exe: Native' has exited with code -1073741819 (0xc0000005).

Im not exactly sure what these errors are and what they mean if i could get some help that would be amazing thank you!!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

喵星人汪星人 2024-11-05 20:40:30

变量 char name[20] 在离开第一个 for() 后无效。

您应该将构造函数中的数组值复制到 Champion 内的数组或动态为该名称分配内存。

这是一种选择:

#include <stdio.h>
#include <string.h>

class Champion {
  char name[20];

 public:

 Champion(const char theName[],int size ){

  for( int i=0;i < size; i++ ){
    name[i] = theName[i];
  }
 }
 const char* getName(){
  return name;
 }
};

int main(int argc, const char* argv[]){

 Champion *c;
 const char name[] = "vamos";
 c = new Champion(name,strlen(name));
 printf("%s",c->getName());
 return 0;
}

The variable char name[20] is not valid after leaving the first for()

You should copy the value of the array in the constructor to an array inside Champion or dynamically allocate memory for the name.

This is one option:

#include <stdio.h>
#include <string.h>

class Champion {
  char name[20];

 public:

 Champion(const char theName[],int size ){

  for( int i=0;i < size; i++ ){
    name[i] = theName[i];
  }
 }
 const char* getName(){
  return name;
 }
};

int main(int argc, const char* argv[]){

 Champion *c;
 const char name[] = "vamos";
 c = new Champion(name,strlen(name));
 printf("%s",c->getName());
 return 0;
}
一刻暧昧 2024-11-05 20:40:30

让我惊讶的一件事是 Champion 构造函数:

Champion::Champion(char name1[])
{
}

它不会对字符数组执行任何操作 - 它不会初始化任何“name”成员。当这个名字稍后被分发时,它是空的,还是更糟糕的是,垃圾?您可能需要将该参数复制到您的成员变量中,以便您有一个稍后可以使用的名称。

One thing that jumps out at me is the Champion constructor:

Champion::Champion(char name1[])
{
}

This doesn't do anything with the character array -- it doesn't initialize any "name" member. WHen the name is handed out later, is it null, or worse, garbage? You presumably need to copy that argument into your member variable, so you have a name you can use later.

以往的大感动 2024-11-05 20:40:30

您的循环仅运行 4 次,因此最后一个 Champion 指针永远不会被初始化。

for(i = 0; i < 4; i++)

应该更改为:

for(i = 0; i < 5; i++)

此外,您的 Champion 类的任何成员都没有在构造函数中初始化,因此读取它们将导致未定义的行为。

您编写的代码或多或少是带有类的 C 代码。查找std::string,它会让你的代码更简单、更正确。现在,您的程序包含多个缓冲区溢出漏洞和悬空指针。

如果我是邪恶的,我会创建一个名称远超过 20 个字符的 Tank,并且可能会使您的程序崩溃,或更糟的是,通过覆盖您的文本段来执行任意代码。

Your loop only runs 4 times, so the last Champion pointer is never initialized.

for(i = 0; i < 4; i++)

Should be changed to:

for(i = 0; i < 5; i++)

Also none of the members of your Champion class are initialized in the constructor, so reading them will cause undefined behaviour.

The code you wrote is more or less C with classes. Look up std::string, it will make your code much simpler and more correct. As it is right now, your program contains multiple buffer overflow vulnerabilities and dangling pointers.

If I were evil, I would create a Tank with a name much longer than 20 characters and likely be able to crash your program or worse, execute arbitrary code by overwriting your text segment.

一向肩并 2024-11-05 20:40:30

检查

return name;

名称在

Champion::getName()

哪里定义?
是否已初始化?


当您在构造函数中执行 name = name1 时,您只是复制指针。
对于您的程序,这是指向 for 循环中的局部变量的指针。
一旦离开 for 循环,该变量就会超出范围。
您应该使用 std::string::copy()strcpy() 复制您的字符串。

check the

return name;

in

Champion::getName()

where is name defined?
Is it initialized?


When you do name = name1 in the constructor, you are just copying the pointer.
In the case of your program, this is a pointer to a local variable in your for loop.
That variable goes out of scope once you leave that for loop.
You should use std::string::copy() or strcpy() to copy your string.

月竹挽风 2024-11-05 20:40:30

如果指针成员没有指向堆或堆栈上的任何地址,请养成将构造函数中的指针成员设置为 0 (NULL) 的习惯。这样做将使您免受 0xcc...无效地址的影响。如果您已使用完该指针,即使该指针是双指针的一部分,也请在释放它所指向的对象后将其设置回 0。您有责任编写代码来执行此操作。另一种选择是使用托管内存编程语言。

对于您的代码,

Champion** champ = (Champion**)malloc(sizeof(Champion*) * 5);
// or
Champion** champ = (Champion**)calloc(5, sizeof(Champion*));
// or
Champion** champ = new Champion*[5];

您选择分配冠军双指针的方式取决于您。我更喜欢 (Champion**)malloc(sizeof(Champion*) * 5) 因为我习惯了 C 风格编码。

Make it a habit to set the pointer members to 0 (NULL) is the constructor if they are not pointing to any address on the heap or on the stack. Doing this will save you from the 0xcc... invalid addresses. If you are done with the pointer even if the pointer is part of a double pointer, set it back to 0 after free the object which it points to. It is your responsibility which writing the code to do so. The other option is go do a managed memory programming language instead.

And with your code, it's

Champion** champ = (Champion**)malloc(sizeof(Champion*) * 5);
// or
Champion** champ = (Champion**)calloc(5, sizeof(Champion*));
// or
Champion** champ = new Champion*[5];

Which way you choose to allocation the champ double pointer is up to you. I prefer (Champion**)malloc(sizeof(Champion*) * 5) because I am used to C style coding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文