void new_test() {int** pp;pp = new int*[10];for(int i=0; i<10; ++i){pp[i] = new int[10];}//pp[0], pp[1], ... , pp[9]在内存中连续;//a1 = pp[0][0], pp[0][1], ... , pp[0][9]在内存中也是连续的;//a2 = pp[1][0], pp[1][1], ... , pp[1][9]在内存中也是连续的;//...//a9 = pp[9][0], pp[9][1], ... , pp[9][9]在内存中也是连续的;//然而 pp[0][9]与pp[1][0]是不连续的,pp[1][9]与pp[2][0]也不连续;//即用new申请的动态堆内存,一维连续二维不连续;//若从内存地址&(pp[0][0])连续写入10*10个int型数据则内存将会被破坏,然而这种破坏;//是合法的,编译器不会出警告或错误,但程序运行中会出现非常诡异的现象;//如某个变量突然莫名其妙的被改掉了,然而程序中并没有在任何地方改了它; }
以上为简化代码,下面为程序中实际遇到的情况:
void CXAnimation::_loadAnimFromFile(cchar* pfile) {std::ifstream ifs(pfile, std::ios::binary);if(!ifs || !ifs.is_open())return;int num[2], i, iSet = 0, ii = sizeof(int);while(!ifs.eof()){ifs.read((char*)num, ii*2); //num[0] 帧数, num[1] 骨骼数; CXAnimSet animSet;m_animSets.push_back(animSet);CXAnimSet& rset = m_animSets[iSet];rset.nFrame = num[0];rset.pAnims = new float4x4*[num[0]];m_nBones = num[1];//骨骼数总是不变的;m_nb1 = num[1];int nbt = num[1]*16*ii;for(i=0; i<num[0]; ++i){rset.pAnims[i] = new float4x4[num[1]];xeAssert(rset.pAnims[i] != NULL);ifs.read((char*)&(rset.pAnims[i][0]), nbt);}//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@//特别注意: 下面这行代码是错误的,因为二维动态内存是不连续的;//所以下面的代码将导致内存不可预见的更改,比如m_nBones被莫名其妙的改掉了;//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //ifs.read((char*)&(rset.pAnims[0][0]), num[0]*num[1]*16*ii); iSet++;ifs.peek();}//计算骨骼初始变换的逆,方便蒙皮计算时使用,不必每一帧都做重复的运算; _calcInitInversTM();}