C++ STL List复制一个结构,但复制的值被两个内存地址偏移
我在Windows7上使用Code::Blocks编译,使用的是MinGW编译器(我只能假设它是最新版本;Code::Blocks和MinGW都是上周安装的)。我的问题是在特定情况下出现的,我试图编写一个更简单的脚本来演示问题的尝试失败了(这意味着我的结构有问题)。还有,我很抱歉这篇文章写了这么长时间 目前,我正在使用一个类FXSDL,它将充当SDL包装器:C++ STL List复制一个结构,但复制的值被两个内存地址偏移,c++,list,stl,segmentation-fault,C++,List,Stl,Segmentation Fault,我在Windows7上使用Code::Blocks编译,使用的是MinGW编译器(我只能假设它是最新版本;Code::Blocks和MinGW都是上周安装的)。我的问题是在特定情况下出现的,我试图编写一个更简单的脚本来演示问题的尝试失败了(这意味着我的结构有问题)。还有,我很抱歉这篇文章写了这么长时间 目前,我正在使用一个类FXSDL,它将充当SDL包装器: class FXSDL { public: FXSDL(); virtual ~FXSDL();
class FXSDL
{
public:
FXSDL();
virtual ~FXSDL();
int Initialize();
int Render();
FXID CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims);
int SetAnim(FXID hRefID, FXID hAnimID);
FXID hPlayer;
protected:
private:
list<FXSurface> m_lstFXObjects;
list<FXSurface>::iterator m_liFirst;
SDL_Surface* m_lpsfSDLScreen;
Uint32 m_tmOld;
Uint32 m_tmFrame;
};
class FXSDL
{
公众:
FXSDL();
虚拟~FXSDL();
int初始化();
int Render();
FXID CreateCharacter(FXID hRefID、字符串fpImage、int wpxTile、int hpxTile、map htAnims);
int SetAnim(FXID hRefID,FXID hAnimID);
FXID-hPlayer;
受保护的:
私人:
列出mlstfx对象;
列表::迭代器m_liFirst;
SDL_表面*m_LPSFSDL屏幕;
Uint32万欧元;
Uint32 m_tmFrame;
};
我的列表的值类型为:
struct FXSurface
{
FXID hRefID;
int wpxTile;
int hpxTile;
int wpxTotal;
int hpxTotal;
int cntTiles;
map<int, vector<int> > htAnims; // All animations
map<int, vector<int> >::iterator vCurr; // Currently active animation
vector<int>::iterator fiCurr; // Currently active frame
SDL_Surface* lpsfSDL;
SDL_Rect* lprcTiles; // Predefined frame positions
string* fpImage;
};
struct FXSurface
{
FXID-hRefID;
int-wpxTile;
int-hpxTile;
int WPEXTOTAL;
int-hpxTotal;
内景瓷砖;
映射htAnims;//所有动画
map::iterator vCurr;//当前活动的动画
vector::iterator fiCurr;//当前活动帧
SDL_表面*lpsfSDL;
SDL_Rect*lprcTiles;//预定义的帧位置
字符串*fpImage;
};
我已经实现了非常简单的初始化和渲染函数。CreateCharacter函数采用几个参数,其中最重要的是htAnims,这是一个整数向量的映射(其思想是:我使用易于记忆的表示(如FXA_IDLE或FXA_WALK)定义数字ID作为关键,并将表示动画帧的一系列数值作为向量)。这可以相当容易地实现为多维整数数组,但动画的长度是可变的,我希望能够添加新动画(或重新定义现有动画),而无需重新创建数组
CreateCharacter函数很简单。它创建一个新的FXSurface,用所需的数据填充它,并将新的FXSurface推送到列表中:
FXID FXSDL::CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims)
{
//list<FXSurface>::iterator lpsfTemp;
FXSurface lpsfTemp;
list<FXSurface>::iterator lpsfPos;
SDL_Rect* lprcCurr = NULL;
int cntTileW = 0;
int cntTileH = 0;
int cntCurr = 0;
// Start off by initializing our container struct
//lpsfTemp = new FXSurface();
lpsfTemp.lpsfSDL = IMG_Load(fpImage.c_str()); // Try to load the requested image
if(lpsfTemp.lpsfSDL != NULL) // If we didn't fail to
{
// Assign some variables for tracking
lpsfTemp.hRefID = hRefID;
lpsfTemp.fpImage = &fpImage;
lpsfTemp.wpxTotal = lpsfTemp.lpsfSDL->w;
lpsfTemp.hpxTotal = lpsfTemp.lpsfSDL->h;
// If a tile width was specified, use it
if(wpxTile != 0)
{
lpsfTemp.wpxTile = wpxTile;
lpsfTemp.hpxTile = hpxTile;
} // Otherwise, assume one tile
else
{
lpsfTemp.wpxTile = lpsfTemp.wpxTotal;
lpsfTemp.hpxTile = lpsfTemp.hpxTotal;
}
// Determine the tiles per row and column for later
cntTileW = lpsfTemp.wpxTotal / lpsfTemp.wpxTile;
cntTileH = lpsfTemp.hpxTotal / lpsfTemp.hpxTile;
// And the total number of tiles
lpsfTemp.cntTiles = cntTileW * cntTileH;
lpsfTemp.lprcTiles = new SDL_Rect[cntTileW*cntTileH];
// So we don't calculate this every time, determine each frame's coordinates and store them
for(int h = 0; h < cntTileH; h++)
{
for(int w = 0; w < cntTileW; w++)
{
cntCurr = (h*cntTileW)+w;
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
}
}
// Now acquire our list of animations and set the default
//lpsfTemp.htAnims = new map<int, vector<int> >(*htAnims);
lpsfTemp.htAnims = htAnims;
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
this->m_lstFXObjects.push_back(lpsfTemp);
}
else
{
hRefID = 0;
}
return hRefID;
}
FXID FXSDL::CreateCharacter(FXID hRefID、字符串fpImage、int-wpxTile、int-hpxTile、map-htAnims)
{
//列表::迭代器lpsfTemp;
FX表面lpsfTemp;
列表::迭代器lpsfPos;
SDL_Rect*lprcCurr=NULL;
int cntTileW=0;
int cntTileH=0;
int cntCurr=0;
//从初始化容器结构开始
//lpsfTemp=新的FXSurface();
lpsfTemp.lpsfSDL=IMG_Load(fpImage.c_str());//尝试加载请求的映像
if(lpsfTemp.lpsfSDL!=NULL)//如果我们没有失败
{
//为跟踪分配一些变量
lpsfTemp.hRefID=hRefID;
lpsfTemp.fpImage=&fpImage;
lpsfTemp.wpxTotal=lpsfTemp.lpsfSDL->w;
lpsfTemp.hpxTotal=lpsfTemp.lpsfSDL->h;
//如果指定了平铺宽度,请使用它
如果(wpxTile!=0)
{
lpsfTemp.wpxTile=wpxTile;
lpsfTemp.hpxTile=hpxTile;
}//否则,假设一个平铺
其他的
{
lpsfTemp.wpxTile=lpsfTemp.wpxTotal;
lpsfTemp.hpxTile=lpsfTemp.hpxTotal;
}
//确定每行和每列的瓷砖,以便以后使用
cntTileW=lpsfTemp.wpxTotal/lpsfTemp.wpxTile;
cntTileH=lpsfTemp.hpxTotal/lpsfTemp.hpxTile;
//以及瓷砖的总数
lpsfTemp.cntTiles=cntTileW*cntTileH;
lpsfTemp.lprcTiles=新SDL_Rect[cntTileW*cntTileH];
//所以我们不是每次都计算这个,而是确定每一帧的坐标并存储它们
对于(int h=0;hw=lpsfTemp.wpxTile;
lprcCurr->h=lpsfTemp.hpxTile;
lprcCurr->x=w*lpsfTemp.wpxTile;
lprcCurr->y=h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr]=*lprcCurr;
lprcCurr=NULL;
}
}
//现在获取我们的动画列表并设置默认值
//lpsfTemp.htAnims=新地图(*htAnims);
lpsfTemp.htAnims=htAnims;
lpsfTemp.vCurr=lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr=lpsfTemp.vCurr->second.begin();
这->m_lstFXObjects.push_back(lpsfTemp);
}
其他的
{
hRefID=0;
}
返回hRefID;
}
正是在推送对象时发生了错误。我已经过了很多次了。起初,我只能判断迭代器无法取消对FXSurface对象的引用。在使用手表识别迭代器和列表对象指向的确切内存地址并取消对该地址的引用后,我注意到了SEGFULTS的原因:当列表对象复制它时,我放入原始FXSurface中的所有值都向下推两个内存块
我这样做的过程很简单。我在CreateCharacter的return语句中设置了一个断点,它为我提供了lpsfTemp(稍后添加到列表中的FXSurface)和mlstfxObjects(我将其添加到的列表)的视图。我滚动浏览mlstfxobjects的成员,这会将我带到_m_节点,它包含到目前为止我添加的唯一对象的内存地址。我在这里以(FXSurface)-十六进制地址的形式将手表添加到此地址-
首先,找到地址:
(这里应该有一张图片,显示突出显示的_M_node属性,其中包含列表项的地址,但我不能发布图片,我只能发布一个URL。第二个更重要。它位于)
下一步,我们投票并尊重地址。此图显示了lpsfTemp和m_lstFX中的副本
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
SDL_Rect tmpRect;
tmpRect.w = lpsfTemp.wpxTile;
tmpRect.h = lpsfTemp.hpxTile;
tmpRect.x = w*lpsfTemp.wpxTile;
tmpRect.y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = tmpRect;
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();