游戏开发中动态数组执行delete []触发Segmentation Fault问题求助
解决动态数组存储Player时的Segmentation Fault问题
你遇到的段错误根源是错误地使用memcpy来拷贝包含非POD类型(比如std::string)的对象数组。咱们一步步拆解问题,再给出修复方案:
问题核心原因
memcpy是字节级的浅拷贝工具,它只适合处理POD(Plain Old Data)类型——也就是没有自定义构造/析构函数、内部成员都是基础数据类型的对象。而你的Player类包含std::string,这个类型内部管理着堆内存,浅拷贝会导致致命问题:
- 第一次添加玩家时,
PlayerList是NULL,memcpy没执行操作,暂时没问题; - 第二次添加玩家时,
memcpy把旧数组里的Player字节拷贝到新数组,此时新、旧数组里的Player对象的PlayerName(std::string)指向同一块堆内存; - 调用
delete [] PlayerList释放旧数组时,旧数组里的Player析构函数会触发std::string的析构,释放那块堆内存; - 第三次添加玩家时,新数组里的
Player的PlayerName已经是野指针了,再次执行delete []时,程序尝试释放已经被释放过的内存,直接触发段错误。
修复方案:用逐对象拷贝替代memcpy
我们需要调用Player的赋值运算符来完成深拷贝,这样std::string会正确复制内部的堆内存,避免野指针和双重释放。修改resizePlayerList函数如下:
void Game::resizePlayerList() { if(NewPlayer.getPlayerName() != "") { // 原条件"No Name"和默认构造的""不匹配,这里统一成空字符串判断 int newSize = NPlayers + 1; Player* newArr = new Player[newSize]; // 逐对象拷贝,触发Player的赋值运算符,std::string会完成深拷贝 for(int i = 0; i < NPlayers; ++i) { newArr[i] = PlayerList[i]; } NPlayers = newSize; delete [] PlayerList; PlayerList = newArr; PlayerList[NPlayers-1] = NewPlayer; } }
额外优化建议
- 修复Game类的内存泄漏:当前
Game的析构函数是空的,会导致PlayerList的内存永远无法释放,补充析构逻辑:
Game::~Game() { delete [] PlayerList; };
- 替换手动动态数组为
std::vector:你已经注释掉了std::vector<Player> PlayerList2;,其实std::vector会自动管理内存扩容和释放,完全不需要手动写resize逻辑,代码会更简洁安全:
// 把Game类里的Player* PlayerList;改成: std::vector<Player> PlayerList; // 然后resizePlayerList可以简化成: void Game::resizePlayerList() { if(NewPlayer.getPlayerName() != "") { PlayerList.push_back(NewPlayer); // NPlayers也可以去掉,直接用PlayerList.size()获取玩家数量 } }
- 避免头文件里的
using namespace std;:头文件里使用这个会污染全局命名空间,建议头文件里用std::string、std::cout这样的前缀,只在实现文件里按需使用using namespace std;。
修改后运行你的主函数,三次添加玩家都会正常执行,PrintList也会正确输出所有玩家信息,不会再触发段错误。
内容的提问来源于stack exchange,提问作者Pedro R.
相关产品推荐
相关产品推荐

