我有以下程序,每次我运行它有时(大多数时候)我收到堆损坏错误
我不能把手指放在它发生的地方,因为每次运行都会在我的程序中的不同位置弹出.
请问有人能说些什么吗?
当我试图释放p时,PS堆损坏也会弹出
提前致谢
#define _CRT_SECURE_NO_WARNINGS #include "stdafx.h" #include#include 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; } }
koalo.. 7
我没有查看整个代码,但有一些工具可以帮助您在这种情况下跟踪内存的使用情况并指出是否出现了问题.一个例子是至少可用于Linux环境的valgrind.无论如何,这个工具允许我在你的代码中找到至少一个bug,如下所示.
编译调试信息.如果您使用的是gcc,请使用-g命令行标志,例如
g++ foo.cpp -g -o foo -std=gnu++11
用valgrind运行
valgrind ./foo
看看输出
==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)
显然,根据此输出,您在第155行遇到问题
==6423== Invalid write of size 8 ==6423== at 0x4011FF: getAllPlayersStartWithA(team_t*) (foo.cpp:155)
如果我们仔细观察,我们会看到以下内容:
player_t **p = new player_t*[sum + 1]; for (int i = 0; i < team->maxOfPlayers; i++) { p[i] = NULL; }
您创建一个大小为+ 1的数组,但是将其迭代到team-> maxOfPlayers,它们可能相同或不同.这意味着您要写入要修改的数组外部的某些内存,因此您可以在堆中的某处写入您不应该写入的内容(导致堆损坏).
这至少是一个问题.重复1.-4.直到valgrind没有别的抱怨.
我没有查看整个代码,但有一些工具可以帮助您在这种情况下跟踪内存的使用情况并指出是否出现了问题.一个例子是至少可用于Linux环境的valgrind.无论如何,这个工具允许我在你的代码中找到至少一个bug,如下所示.
编译调试信息.如果您使用的是gcc,请使用-g命令行标志,例如
g++ foo.cpp -g -o foo -std=gnu++11
用valgrind运行
valgrind ./foo
看看输出
==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)
显然,根据此输出,您在第155行遇到问题
==6423== Invalid write of size 8 ==6423== at 0x4011FF: getAllPlayersStartWithA(team_t*) (foo.cpp:155)
如果我们仔细观察,我们会看到以下内容:
player_t **p = new player_t*[sum + 1]; for (int i = 0; i < team->maxOfPlayers; i++) { p[i] = NULL; }
您创建一个大小为+ 1的数组,但是将其迭代到team-> maxOfPlayers,它们可能相同或不同.这意味着您要写入要修改的数组外部的某些内存,因此您可以在堆中的某处写入您不应该写入的内容(导致堆损坏).
这至少是一个问题.重复1.-4.直到valgrind没有别的抱怨.