我有以下程序,每次运行时(大多数时候)我都会遇到堆损坏错误
我不能把手指放在它发生的地方,因为它在我的程序的不同位置弹出。
有人可以说些什么吗?
当我试图释放p
时,P / S堆损坏也会弹出提前致谢
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include<iostream>
#include<string.h>
using namespace std;
const int MAX_OF_PLAYERS = 10;
const int SIZE = 100;
struct player_t {
char *name;
int numOfShirt;
};
struct team_t {
char *nameOfTeam;
int maxOfPlayers;
int numOfPlayers;
player_t *players;
};
void readPlayer(player_t *player);
void initTeam(team_t *team);
void addPlayer(team_t *team);
void printTeam(team_t *team);
void freeAll(team_t *team);
player_t** getAllPlayersStartWithA(team_t *team);
void printAteam(player_t **p);
int main()
{
team_t t;
player_t **p;
initTeam(&t);
addPlayer(&t);
addPlayer(&t);
printTeam(&t);
p = getAllPlayersStartWithA(&t);
if (p[0] != NULL)
printAteam(p);
system("pause");
freeAll(&t);
//delete[] p;
}
void readPlayer(player_t *player)
{
char name[SIZE];
cout << " please enter the name of the player " << endl;
cin >> name;
cout << " please enter the num of the shirt " << endl;
cin >> player->numOfShirt;
int size = strlen(name);
char *res = new char[size + 2];
strcpy(res, name);
player->name = res;
}
void initTeam(team_t *team)
{
char name[SIZE];
// get the team name
cout << " please enter your team name" << endl;
cin >> name;
// get the name length
int size = strlen(name);
// allocate new array with length size
team->nameOfTeam = new char[size + 1];
// copy the string to the new array
strcpy(team->nameOfTeam, name);
// get the number of max players
cout << "please enter the number of the max players on your team" << endl;
cin >> team->maxOfPlayers;
// create new players array
player_t *players = new player_t[team->maxOfPlayers];
// initial the players array
for (int i = 0; i < team->maxOfPlayers; i++)
{
players[i] = { 0 };
}
//bind the array to team
team->players = players;
// set current players to 0
team->numOfPlayers = 0;
}
void addPlayer(team_t *team)
{
for (int i = 0; i < team->maxOfPlayers; i++)
{
if (team->players[i].name == NULL)
{
readPlayer(team->players + i);
break;
}
}
}
void printTeam(team_t *team)
{
cout << "Team name: ";
cout << team->nameOfTeam << endl;
cout << "Max Number of players in team: ";
cout << team->maxOfPlayers << endl;
cout << "Current number of players in team: ";
cout << team->numOfPlayers << endl;
cout << "Team Players:" << endl;
for (int i = 0; i < team->maxOfPlayers; i++)
{
if (team->players[i].name)
{
cout << "Player name: ";
cout << team->players[i].name;
cout << ", ";
cout << "Player shirt: ";
cout << team->players[i].numOfShirt << endl;
}
}
cout << endl;
}
void freeAll(team_t *team)
{
for (int i = 0; i < team->maxOfPlayers; i++)
{
if ((team->players + i)->name != NULL)
delete[](team->players + i)->name;
}
delete[] team->players;
}
player_t** getAllPlayersStartWithA(team_t *team)
{
int sum = 0, position = 0;
for (int i = 0; team->players[i].name != NULL; i++)
{
if (team->players[i].name[0] == 'a' || team->players[i].name[0] == 'A')
{
sum++;
}
}
player_t **p = new player_t*[sum + 1];
for (int i = 0; i < team->maxOfPlayers; i++)
{
p[i] = NULL;
}
for (int i = 0; team->players[i].name != NULL; i++)
{
if (team->players[i].name[0] == 'a')
{
p[position++] = team->players + i;
}
}
return p;
}
void printAteam(player_t **p)
{
cout << "Players start with 'A': " << endl;
for (int i = 0; p[i] != NULL; i++)
{
cout << "Player name: ";
cout << (p[i]->name);
cout << ", ";
cout << "Player shirt: ";
cout << (p[i]->numOfShirt) << endl;
}
}
答案 0 :(得分:6)
我没有查看整个代码,但是有一些工具可以帮助您在这种情况下跟踪内存使用情况并指出是否出现问题。一个例子是至少可用于Linux环境的valgrind。无论如何,这个工具允许我在你的代码中找到至少一个错误,如下所示。
编译调试信息。如果您使用的是gcc,请使用-g命令行标志,例如
com.yourproject
使用valgrind运行
g++ foo.cpp -g -o foo -std=gnu++11
查看输出
valgrind ./foo
显然,根据此输出,第155行存在问题
==6423== Memcheck, a memory error detector
==6423== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6423== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==6423== Command: ./foo
==6423==
please enter your team name
sdfads
please enter the number of the max players on your team
3
please enter the name of the player
efwf
please enter the num of the shirt
5
please enter the name of the player
dsfdsa
please enter the num of the shirt
3
Team name: sdfads
Max Number of players in team: 3
Current number of players in team: 0
Team Players:
Player name: efwf, Player shirt: 5
Player name: dsfdsa, Player shirt: 3
==6423== Invalid write of size 8
==6423== at 0x4011FF: getAllPlayersStartWithA(team_t*) (foo.cpp:155)
==6423== by 0x400C08: main (foo.cpp:38)
==6423== Address 0x5ab6668 is 0 bytes after a block of size 8 alloc'd
==6423== at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6423== by 0x4011CC: getAllPlayersStartWithA(team_t*) (foo.cpp:151)
==6423== by 0x400C08: main (foo.cpp:38)
==6423==
==6423==
==6423== HEAP SUMMARY:
==6423== in use at exit: 72,719 bytes in 3 blocks
==6423== total heap usage: 8 allocs, 5 frees, 74,829 bytes allocated
==6423==
==6423== LEAK SUMMARY:
==6423== definitely lost: 15 bytes in 2 blocks
==6423== indirectly lost: 0 bytes in 0 blocks
==6423== possibly lost: 0 bytes in 0 blocks
==6423== still reachable: 72,704 bytes in 1 blocks
==6423== suppressed: 0 bytes in 0 blocks
==6423== Rerun with --leak-check=full to see details of leaked memory
==6423==
==6423== For counts of detected and suppressed errors, rerun with: -v
==6423== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
如果我们仔细观察,我们会看到以下内容:
==6423== Invalid write of size 8
==6423== at 0x4011FF: getAllPlayersStartWithA(team_t*) (foo.cpp:155)
您创建一个大小为+ 1的数组,但是将其迭代到team-&gt; maxOfPlayers,它们可能相同或不同。这意味着您要写入要修改的数组外部的某些内存,因此您在堆中的某处写入了不应该写入的内容(导致堆损坏)。
这至少是一个问题。重复1.-4。直到valgrind没有别的抱怨。
答案 1 :(得分:1)
您需要更加注意如何访问阵列并跟踪它们的大小。
正如评论已经指出的那样,for (int i = 0; team->players[i].name != NULL; i++)
正在寻找麻烦。你应该确保循环受某些东西约束,要么是players
数组中的条目总数(大概是maxOfPlayers
),要么是当前有效玩家的数量{{1} }。但是,添加新条目时,您的代码实际上永远不会增加numOfPlayers
。
numOfPlayers
中的以下代码也是一个问题:
getAllPlayersStartWithA
player_t **p = new player_t*[sum + 1];
for (int i = 0; i < team->maxOfPlayers; i++)
{
p[i] = NULL;
}
可能比sum + 1
轻得多。在这种情况下,for循环将覆盖超出数组末尾的内存。这很可能是您当前堆损坏错误的原因。