C++ 访问冲突读取位置0xCDCD。C++;

C++ 访问冲突读取位置0xCDCD。C++;,c++,memory,unhandled-exception,C++,Memory,Unhandled Exception,基本上,我现在要做的是构建一个程序,允许你从3个不同的类(坦克、梅勒、远程)中选择,当你选择这个类时,你会给它一个20个或更少字符的名称。在选择5个职业并给每个冠军一个名字后,它会打印出你选择的每个职业的名字和健康状况。代码是这样的: #include "Driver.h" #include <stdio.h> #include "Mele.h" #include "Ranged.h" #include "Tank.h" int main(void) { Champion *c

基本上,我现在要做的是构建一个程序,允许你从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;
}
然后我有另外4门课叫坦克、远程和梅勒;所有这些都继承自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).

我不太清楚这些错误是什么,如果我能得到一些帮助的话,它们意味着什么,那将是令人惊讶的,谢谢

有一件事让我大吃一惊,那就是冠军构造函数:

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

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

您的循环仅运行4次,因此最后一个冠军指针从未初始化

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

应改为:

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

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

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

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

检查

return name;

名称在哪里定义? 它初始化了吗


当您在构造函数中执行
name=name1
时,您只是在复制指针。 在程序中,这是指向for循环中局部变量的指针。 一旦您将该变量留给循环,该变量将超出范围。
您应该使用或来复制字符串。

将第一个for()保留后,变量char name[20]无效

您应该将构造函数中数组的值复制到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;
}
#包括
#包括
班级冠军{
字符名[20];
公众:
冠军(常量字符名称[],整数大小){
对于(int i=0;igetName());
返回0;
}

如果指针成员未指向堆或堆栈上的任何地址,则习惯将其设置为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];

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

另外,作为将来的参考,0xCDCD通常意味着您指向未初始化的内存。因此,这通常是一个很好的迹象,表明您忘记设置某些内容。您好,感谢您帮助实现字符串。h修复了这个问题,以及我没有初始化内存的事实。我最后做的是在champion构造函数中对名称执行malloc,以设置正在实现的字符串名称的大小!谢谢大家的帮助!不,它仍然运行5次0到4,运行整整5次,因为你从0开始,然后是1,然后是2,一直到4。您必须从0到5,因为所有数组都从0开始,而不是从0开始1@Ziekle,使用for循环的方式只能访问
0
3
,而不能访问
4
。要么把它改成这个答案中所说的,要么改成
@Zieklecknerizer Nope,循环永远不会以i=4运行,因为你使用的是严格的less运算符!非常感谢。不幸的是,我按照您所说的做了,并将其设置为在头文件中定义的名称,然后在构造函数中对其进行初始化。我本来会在头球上插上一脚,但我不想在卢兹身上插太多的信息
#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;
}
Champion** champ = (Champion**)malloc(sizeof(Champion*) * 5);
// or
Champion** champ = (Champion**)calloc(5, sizeof(Champion*));
// or
Champion** champ = new Champion*[5];