Stack overflow while serializing large object network in MFC
Bart van Haaff -- BARTHAAF@docuaccess.nl Tuesday, November 26, 1996 Environment: MSVC1.52, NT4.0 Hi, I try to serialize a pretty large and complex network of objects using MFC's serialize method. This works fine for me until a certain limit in the number of objects has been reached, My app crashes because of a stack overflow (current stack size 42 Kb, and I do not have any more space in the data segment). I have tried the following code to enlarge stack but this crashes on the statement: ar >> m_pRootObject; The crash happens immediate when I hit 'Step into (F8)' in the debugger. // testcode void CMyDoc::Serialize(CArchive& ar) { // save some things in statics to survive stack switch static CMyRootClass* pRootObject=NULL; static CString strFileName=GetPathName(); HANDLE hStack=GlobalAlloc(GPTR,63L*1024L); LPSTR pStack=(LPSTR)GlobalLock(hStack); // some obscure win3.0 API call SwitchStackTo(HIWORD(pStack),(UINT)(63L*1024L),0); // normal serialize code CFile f; if(f.Open(strFileName, CFile::modeRead)) { CArchive ar(&f,CArchive::load); // hit F8 to crash..... ar >> m_pRootObject; } ar.Close(); f.Close(); SwitchStackBack(); GlobalUnlock(hStack); GlobalFree(hStack); } The nature of serialize() is recursive and there is not much to do about that, I checked out MFC's source code and the CArchive and CRuntimeClass read/write code, there are some non-static local variables in the code that eat a little stack space for each recursive level. In my own serialize code I declared all locals as 'static'. I hope somebody can give some tips/hints, please don't tell me to: * use 32-bits (I know, but my customers don't) * change the structure of my object model (its to late for that) * stop using MFC (I like some parts of it) Thanks a lot.... Bart van Haaff (barthaaf@docuaccess.nl) Senior Software Developer Document Access B.V. The Netherlands
Alexander Sasha Grinshpun -- alexgr@mercury.co.il Thursday, November 28, 1996 You don't have to change your object model, just change the way your network of objects are serialized. Let's take a look at pseudocode of serializing a graph. class Node { SomeUsefullData data; ListOfPointersToEdge edges; Serialize(CArchive &ar) { data.Serialize(ar); edges.Serialize(ar); // (1) }; }; class Edge { Node *source; Node *target; Serialize(CArchive &ar) { if(ar.IsLoading()) { ar >> source; // Here we may enter into a deep recursion because target may be // not serialized yet ar >> target; } else { ar << source; ar << target; } } }; class Graph { ListOfPointerToNodes nodes; Serialize(CArchive &ar) { nodes.Serialize(ar); } }; Such a serialization of the Graph will cause a deep Serialize recursion. The cause of this recursion is serialization of the edges of the node inside the node itself. The following change in serialization will fix the problem: Node::Serialize(ar) { // We are serializing just a data and delegating responsibility // of graph structure serializing to Graph itself data.Serialize(ar); } Graph::Serialize(ar) { nodes.Serialize(); // Pay attention, that here we will not enter a deep recursion in the // edge serialization because all nodes are already serialized for eache pnode in nodes { pnode->edges.Serialize(); } } I hope it's helpful for you. -- Sasha. Bart van Haaff wrote: > > Environment: MSVC1.52, NT4.0 > > Hi, > > I try to serialize a pretty large and complex network of objects using > MFC's serialize method. This works fine for me until a certain limit in > the number of objects has been reached, My app crashes because of a stack > overflow (current stack size 42 Kb, and I do not have any more space in > the data segment). > > I have tried the following code to enlarge stack but this crashes on the > statement: > ar >> m_pRootObject; > > The crash happens immediate when I hit 'Step into (F8)' in the debugger. > > // testcode > void CMyDoc::Serialize(CArchive& ar) > { > // save some things in statics to survive stack switch > static CMyRootClass* pRootObject=NULL; > static CString strFileName=GetPathName(); > > HANDLE hStack=GlobalAlloc(GPTR,63L*1024L); > LPSTR pStack=(LPSTR)GlobalLock(hStack); > // some obscure win3.0 API call > SwitchStackTo(HIWORD(pStack),(UINT)(63L*1024L),0); > // normal serialize code > CFile f; > if(f.Open(strFileName, CFile::modeRead)) > { > CArchive ar(&f,CArchive::load); > // hit F8 to crash..... > ar >> m_pRootObject; > } > ar.Close(); > f.Close(); > SwitchStackBack(); > GlobalUnlock(hStack); > GlobalFree(hStack); > } > > The nature of serialize() is recursive and there is not much to do about > that, I checked out MFC's source code and the CArchive and CRuntimeClass > read/write code, there are some non-static local variables in the code > that eat a little stack space for each recursive level. In my own > serialize code I declared all locals as 'static'. > > I hope somebody can give some tips/hints, please don't tell me to: > * use 32-bits (I know, but my customers don't) > * change the structure of my object model (its to late for that) > * stop using MFC (I like some parts of it) > > Thanks a lot.... > > Bart van Haaff (barthaaf@docuaccess.nl) > Senior Software Developer > Document Access B.V. > The Netherlands -- ---- Thanks, Sasha.
rick cameron -- rick_cameron@msn.com Thursday, November 28, 1996 We had a similar problem. Our solution was to change the serialization code. Our document contains a list of sections; each section has a list of objects. An object may be attached to a guideline, and a guideline may connect objects in several sections. We found that the following was happening: document serializes first section section serializes objects object serializes guideline guideline serializes all attached objects (which may jump into another section) object serializes its section section serializes objects ...etc... It was possible for all objects to be serialized as a result of the call to serialize the first section - and, if there were several guidelines, recursion could become quite deep. The solution was to change the Serialize member of the guideline class so that it didn't serialize its attached objects. When loading the document, each object reattaches itself to its guideline. The reason I've gone into some detail is to point out that there may be a way that you can change your serialization code to reduce the amount of cross-coupling and recursion, without changing your object model. Instead of serializing a pointer to an object, reconnect when loading. - rick owner-mfc-l@majordomo.netcom.com on behalf of Bart van Haaff wrote: > > Environment: MSVC1.52, NT4.0 > > Hi, > > I try to serialize a pretty large and complex network of objects using > MFC's serialize method. This works fine for me until a certain limit in > the number of objects has been reached, My app crashes because of a stack > overflow (current stack size 42 Kb, and I do not have any more space in > the data segment). > > I have tried the following code to enlarge stack but this crashes on the > statement: > ar >> m_pRootObject; > > The crash happens immediate when I hit 'Step into (F8)' in the debugger. > > // testcode > void CMyDoc::Serialize(CArchive& ar) > { > // save some things in statics to survive stack switch > static CMyRootClass* pRootObject=NULL; > static CString strFileName=GetPathName(); > > HANDLE hStack=GlobalAlloc(GPTR,63L*1024L); > LPSTR pStack=(LPSTR)GlobalLock(hStack); > // some obscure win3.0 API call > SwitchStackTo(HIWORD(pStack),(UINT)(63L*1024L),0); > // normal serialize code > CFile f; > if(f.Open(strFileName, CFile::modeRead)) > { > CArchive ar(&f,CArchive::load); > // hit F8 to crash..... > ar >> m_pRootObject; > } > ar.Close(); > f.Close(); > SwitchStackBack(); > GlobalUnlock(hStack); > GlobalFree(hStack); > } > > The nature of serialize() is recursive and there is not much to do about > that, I checked out MFC's source code and the CArchive and CRuntimeClass > read/write code, there are some non-static local variables in the code > that eat a little stack space for each recursive level. In my own > serialize code I declared all locals as 'static'. > > I hope somebody can give some tips/hints, please don't tell me to: > * use 32-bits (I know, but my customers don't) > * change the structure of my object model (its to late for that) > * stop using MFC (I like some parts of it) > > Thanks a lot.... > > Bart van Haaff (barthaaf@docuaccess.nl) > Senior Software Developer > Document Access B.V. > The Netherlands > >
| Вернуться в корень Архива |