google key words: "rose" "逆向" "死机"
现象描述: 工程完成了,现在要写文档, 准备先用Rose2003逆向生成类图.
共65个类, update model, 进行到21/65时死掉。等了1小时,还没动静. 直接可以关掉.
然后不全逆向,从上到下,挑着单独逆向。逆向了10几个类。
发现过不去的类是我写的一个数据类, 这个数据类很简单,继承来的. 上边有2层基类.
想到的解决方法:
先建立一个小工程,把数据类加进去。然后逆向, 观察一下,问题到底在哪。
按理说,哪个数据类出了用到mfc内建的类, 没有再用其他东西.
网上资料有个案例:他和我正相反,他是update code死机,解决方法是删掉工程中的.c, .h, 那哥们真聪明,居然能相处这样的解决方法.
<2011_0302>
上面不能对简单的数据类进行反向的情况已经在重新搭建的实验工程上重现出来了。
* 建立一个MDI工程, 如果直接对这个工程进行反向是可以的.
* 建立一个目录DataClass, 里面放上数据类和他的基类文件和基类的基类文件.
* 在工程的doc类中,加入数据类的定义, 声明一个数据类成员变量的指针.
* 在Doc类的构造, 析构, OnNewDocument处假装用一下.
反向时, 也是到这个数据类时,就死掉了, 关掉反向对话框时, Rose退出.
现在需要做实验, 看第一个数据基类是否能反向,第二个数据基类是否能反向, 是否和数据类的实现文件在子文件夹DataClass有关.
对数据类的上一层基类反向正常, 对数据类的第一个基类反向不正常.
不知道问题哪里,还需要继续实验. 那个基类看不出有何特别.
暂时放弃用rose反向, 以后用Rose正向,看看第一个数据类和手工生成的有何区别.
不能反向的第一个基类如下:
// DataWarpper_Base.h: interface for the CDataWarpper_Base class. // ////////////////////////////////////////////////////////////////////// //_DATAWARPPER_BASE_H_ #if !defined(_DATAWARPPER_BASE_H_) #define _DATAWARPPER_BASE_H_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // 数据类的架子 #include <crtdbg.h> //#define G_B_DATAWARPPER_DEBUG /**< CDataWarpper调试标记 */ #define G_CS_DATAWARPPER_DEFAULT_NAME "DataWarpper.dat" #define G_CS_DATAWARPPER_BRIEF "方便的数据类封装" /** * 用__int64值BCD码表示的版本标记 * 年_月日_时分_版本累计号码 * 2010_1103_2353_0000 */ #define G_N64_DATAWARPPER_VERSION 0x2010110400200001/** 0xffffeeddccbbaaaa */; class CDataWarpper_Base : public CObject { DECLARE_SERIAL(CDataWarpper_Base) public: CDataWarpper_Base(); virtual ~CDataWarpper_Base(); //rhs means 'right hand side' CDataWarpper_Base(CDataWarpper_Base& rhs); CDataWarpper_Base& operator= (CDataWarpper_Base& rhs); int LoadDefaultData(); int SaveDefaultData(); int LoadData(PCHAR pFileName); int SaveData(PCHAR pFileName); CString GetProcessPath(); CString GetPathFromFilePathName(PCHAR pcFilePathName); void CopyPchar(PCHAR * ppMsgDst, PCHAR pMsgSrc); void DelPchar(PCHAR * ppMsg); void N64ToDWORD(__int64 n64In, DWORD & dwH, DWORD & dwL); void DWORDToN64(__int64 & n64In, DWORD dwH, DWORD dwL); void Serialize_CStringArray(CArchive& ar, CStringArray & csArr); void Serialize_INT64(CArchive& ar, INT64 & n64); void Serialize_PCHAR(CArchive& ar, PCHAR * ppChar); //member function virtual void Dump(); protected: virtual void Init(); virtual void Clear(); virtual void Copy(CDataWarpper_Base& rhs); virtual void Serialize(CArchive& ar); //数据存取函数get, set public: void SetVersion(__int64 n64In) {m_n64Version = n64In;} __int64 GetVersion() {return m_n64Version;} void SetRrief(PCHAR pIn) {CopyPchar(&m_pcBrief, pIn);} PCHAR GeBrief() {return m_pcBrief;} PCHAR GetDataFileName(); void SetDataFileName(PCHAR pIn); //member private: __int64 m_n64Version; /**< 此数据类的代码版本 YYYY_MM_DD HH:MM:SS表示为 0xYYYYMMDDHHMMSS*/ PCHAR m_pcBrief; /**< 此数据类的摘要说明 */ //不需要保存的成员变量 CString m_csDataFileName; /**< 数据类本身要读取和保存时的文件名 */ }; #endif // !defined(_DATAWARPPER_BASE_H_)
// DataWarpper_Base.cpp: implementation of the CDataWarpper_Base class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "DataWarpper_Base.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// IMPLEMENT_SERIAL(CDataWarpper_Base, CObject, VERSIONABLE_SCHEMA | 1); CDataWarpper_Base::CDataWarpper_Base() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("CDataWarpper_Base::CDataWarpper_Base()/n"); #endif Init();//Init call only once } CDataWarpper_Base::~CDataWarpper_Base() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("CDataWarpper_Base::~CDataWarpper_Base()/n"); #endif Clear(); } void CDataWarpper_Base::Init() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::Init()/n"); #endif m_n64Version = G_N64_DATAWARPPER_VERSION; m_pcBrief = NULL; CopyPchar(&m_pcBrief, G_CS_DATAWARPPER_BRIEF); m_csDataFileName.Empty(); } void CDataWarpper_Base::Dump() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::Dump()/n"); #endif TRACE("dump----------------------------------------/n"); DWORD dwVersionH = 0; DWORD dwVersionL = 0; N64ToDWORD(m_n64Version, dwVersionH, dwVersionL); TRACE("m_n64Version = 0x%.8x%.8x/n", dwVersionH, dwVersionL); TRACE("m_pcBrief = %s/n", m_pcBrief); TRACE("m_csDataFileName = %s/n", GetDataFileName()); } void CDataWarpper_Base::Clear() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::Clear()/n"); #endif m_n64Version = 0; DelPchar(&m_pcBrief); } void CDataWarpper_Base::Copy(CDataWarpper_Base& rhs) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::Copy(CDataWarpper_Base& rhs)/n"); #endif m_n64Version = rhs.m_n64Version; CopyPchar(&m_pcBrief, rhs.m_pcBrief); } void CDataWarpper_Base::DelPchar(PCHAR * ppMsg) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::DelPchar(PCHAR * ppMsg)/n"); #endif if(ppMsg && (*ppMsg)) { delete *ppMsg; *ppMsg = NULL; } } void CDataWarpper_Base::CopyPchar(PCHAR * ppMsgDst, PCHAR pMsgSrc) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::CopyPchar(PCHAR * ppMsgDst, PCHAR pMsgSrc)/n"); #endif DelPchar(ppMsgDst); if(!pMsgSrc) return; int nLen = strlen(pMsgSrc); *ppMsgDst = new CHAR[nLen + 1]; _ASSERT(*ppMsgDst); memset(*ppMsgDst, 0, nLen + 1); strcpy(*ppMsgDst, pMsgSrc); } CDataWarpper_Base::CDataWarpper_Base(CDataWarpper_Base& rhs) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("CDataWarpper_Base::CDataWarpper_Base(CDataWarpper_Base& rhs)/n"); #endif Copy(rhs); } CDataWarpper_Base& CDataWarpper_Base::operator= (CDataWarpper_Base& rhs) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("CDataWarpper_Base& CDataWarpper_Base::operator= (CDataWarpper_Base& rhs)/n"); #endif Copy(rhs); return * this; } void CDataWarpper_Base::N64ToDWORD(__int64 n64In, DWORD & dwH, DWORD & dwL) { DWORD dwMaskDWORD = -1; int nSizeDW = sizeof(DWORD); int nSizeN64 = sizeof(__int64); /** __int64是DWORD 容量的2倍*/ dwH = (DWORD)((m_n64Version >> (nSizeDW * 8)) & dwMaskDWORD); dwL = (DWORD)(m_n64Version & dwMaskDWORD); } void CDataWarpper_Base::DWORDToN64(__int64 & n64In, DWORD dwH, DWORD dwL) { int nSizeDW = sizeof(DWORD); n64In = dwH; n64In <<= (nSizeDW * 8); n64In |= dwL; } void CDataWarpper_Base::Serialize_CStringArray(CArchive& ar, CStringArray & csArr) { CString csTmp; INT n = 0; INT nLen = 0; if(ar.IsLoading()) { csArr.RemoveAll(); ar >> nLen; if(nLen > 0) { for(n = 0; n < nLen; n++) { ar >> csTmp; csArr.Add(csTmp); } } } else if(ar.IsStoring()) { nLen = csArr.GetSize(); ar << nLen; if(nLen > 0) { for(n = 0; n < nLen; n++) { csTmp = csArr.GetAt(n); ar << csTmp; } } } } void CDataWarpper_Base::Serialize_INT64(CArchive& ar, INT64 & n64) { DWORD dwH = 0; DWORD dwL = 0; if(ar.IsLoading()) { ar >> dwH; ar >> dwL; DWORDToN64(n64, dwH, dwL); } else if(ar.IsStoring()) { N64ToDWORD(n64, dwH, dwL); ar << dwH; ar << dwL; } } void CDataWarpper_Base::Serialize_PCHAR(CArchive& ar, PCHAR * ppChar) { CString csTmp; if(ar.IsLoading()) { ar >> csTmp; CopyPchar(ppChar, (LPSTR)(LPCSTR)csTmp); } else if(ar.IsStoring()) { csTmp = *ppChar; ar << csTmp; } } void CDataWarpper_Base::Serialize(CArchive& ar) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::Serialize(CArchive& ar)/n"); #endif CString csTmp; DWORD dwVersionH = 0; DWORD dwVersionL = 0; try { Serialize_INT64(ar, m_n64Version); Serialize_PCHAR(ar, &m_pcBrief); if(ar.IsLoading()) {//ar >> xx } else if(ar.IsStoring()) {//ar << xx } } catch (...) { Clear(); } } int CDataWarpper_Base::LoadData(PCHAR pFileName) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("int CDataWarpper_Base::LoadData(PCHAR pFileName)/n"); #endif int nRc = S_OK; CFile file; try { Clear(); if(file.Open(pFileName, CFile::modeRead | CFile::typeBinary)) { CArchive ar(&file, CArchive::load); Serialize(ar); ar.Close(); file.Close(); } else nRc = S_FALSE; } catch(...) { Clear(); nRc = S_FALSE; } return nRc; } int CDataWarpper_Base::SaveData(PCHAR pFileName) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("int CDataWarpper_Base::SaveData(PCHAR pFileName)/n"); #endif int nRc = S_OK; CFile file; try { if(file.Open(pFileName, CFile::modeCreate | CFile::modeReadWrite | CFile::typeBinary)) { CArchive ar(&file, CArchive::store); Serialize(ar); ar.Close(); file.Close(); } else nRc = S_FALSE; } catch(...) { Clear(); nRc = S_FALSE; } return nRc; } CString CDataWarpper_Base::GetProcessPath() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("CString CDataWarpper_Base::GetProcessPath()/n"); #endif CString csPath; DWORD dwRc = 0; int nLenPathName = 4096; PCHAR pPathName = new CHAR[nLenPathName]; _ASSERT(pPathName); memset(pPathName, 0, nLenPathName); dwRc = GetModuleFileName(NULL, pPathName, nLenPathName); _ASSERT(dwRc > 0); csPath = pPathName; delete pPathName; int nPos = csPath.ReverseFind('//'); csPath = csPath.Left(nPos + 1); return csPath; } CString CDataWarpper_Base::GetPathFromFilePathName(PCHAR pcFilePathName) { CString csCfgPathName = pcFilePathName; int nPos = csCfgPathName.ReverseFind('//'); csCfgPathName = csCfgPathName.Left(nPos + 1); return csCfgPathName; } int CDataWarpper_Base::LoadDefaultData() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("int CDataWarpper_Base::LoadDefaultData()/n"); #endif return LoadData(GetDataFileName()); } int CDataWarpper_Base::SaveDefaultData() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("int CDataWarpper_Base::SaveDefaultData()/n"); #endif return SaveData(GetDataFileName()); } PCHAR CDataWarpper_Base::GetDataFileName() { #ifdef G_B_DATAWARPPER_DEBUG TRACE("PCHAR CDataWarpper_Base::GetDataFileName()/n"); #endif if(m_csDataFileName.IsEmpty()) { m_csDataFileName = GetProcessPath(); m_csDataFileName += G_CS_DATAWARPPER_DEFAULT_NAME; } return (LPSTR)(LPCSTR)m_csDataFileName; } void CDataWarpper_Base::SetDataFileName(PCHAR pIn) { #ifdef G_B_DATAWARPPER_DEBUG TRACE("void CDataWarpper_Base::SetDataFileName(PCHAR pIn)/n"); #endif if(pIn && (strlen(pIn) > 0)) m_csDataFileName = pIn; }
查了资料, 不能直接来用RoseIDE来反向c++工程.
用下面的工具对工程进行预处理,导出处理结果为Rose的mdl, 然后才能在Rose中对工程进行更新.
C:/Program Files/Rational/Rose/c++/analyzer.exe
实验了一下, 即使是一个简单的工程,也要手工包含头文件的路径. 细节挺多,有时间再实验。
用rose反向c++源码工程用处倒是蛮大的.