一个23万行代码的移植过程

一、概述
移植完毕后觉得难度并不高,遇到了一些困难,都能顺利解决,最难得是不同编译器之间的差异造成的程序运行结果不同,比如这次移植遇到的内存管理是遇到的主要问题,有一块内存在vc6下正常,到vc8-debug下就总溢出,vc8-release下又好了,最后大家讨论一下,只好归咎于编译器(BILLGATE的错),此问题暂时用简单的条件控制暂时解决,没有全部解决。

移植分几个阶段,第一步打开.dsw工程,vc8会自动形成.sln,以后就用这个了;第二步配置环境,include,lib目录什么的;第三步编译一下,总体看看,写得比较好的代码一般错误很少,比如我移植的代码分为34个子工程,有个工程的只有一个错误,其他都是警告。第四步,修改了所有的错误后就可以编译、链接了,不过一般这个时候还是不能运行的,因为好多警告还是要改的。第五步,最后一步是最难过的,成功失败在此一举,调试运行总是很刺激,不过vc6的mfc貌似还是和vc8的有些不同,所以出了错还是要一步一步地跟踪的,这一步只遇到一个致命问题,最后再讲。

PS:需要强调的是,警告比错误更危险,一定要注意。

二、具体实施
1、配置好环境后先看看(all)工程都包括那些子工程

其中主要依赖关系包括:

第一级的Project all包括:
Project_Dep_Name CPM
Project_Dep_Name scanner
Project_Dep_Name PowerMonitor
Project_Dep_Name HostDiag
Project_Dep_Name DICOMApp

第二级的Project scanner又包括:
Project_Dep_Name EHWemu
Project_Dep_Name ustream
Project_Dep_Name usi_mon_emu
Project_Dep_Name udl
Project_Dep_Name uos

2、从第三级(底层)的uos.dsp开始
编译了一下,只有1 error(s), 14 warning(s),自然先对付错误了:

症状1 //error C2668: 'log10' : ambiguous call to overloaded function
这个容易,vc6下代码这样(DWORD)log10(*((DWORD *)pValue))+2 > dwValueLength )

vc8下看下log10的声明 double __cdecl log10(__in double _X);
改一下!(double)log10(*(double *)pValue)+2 > dwValueLength )

症状2 //warning C4996: 'sscanf' was declared deprecated
这个问题很普遍,就是vc8对原来的很多不安全的函数都发不了_s版本。
直接改为 sscanf_s( pBuff, "%d", &dwDebugFlag ); 参数都没变,真好。

症状3 // _controlfp( puthThread->dwFPControl, MCW_PC );
这个麻烦一点,需要多个参数,那就定义一个unsigned int control_word;
然后改成 _controlfp_s(&control_word,puthThread->dwFPControl, MCW_PC );

类似的包括FILE *pFile = fopen( "1.txt", "wt" );
改为//errno_t err; err = fopen_s(&pFile ,"1.txt", "wt" ););

症状4 // warning C4532: 'return' : jump out of __finally block has undefined behavior during termination handling
说你返回值路径不全面,加几个return就Ok了。

其他不一一列举,都是_s函数的问题,至此一个最简单的工程就搞定了,以下的工程遇到同样问题就不再描述了。

3、借助下一个工程来说一个老问题。
//error C2065: 'i' : undeclared identifier
在这一行 for(i = 0; i < iMaxFocalZones; i++)
其实i是在 for(int i = 0; i < iMaxFocalZones; i++) 定义的
改也容易 把int i 提出来就可以了,不过要仔细察看i的作用域,不要提错了,就大发了。

'atan' : ambiguous call to overloaded function 这个地方我偷懒了。
#define PI (4 * atan(1)) 改为 #define PI 3.1415926535897932384626433832795。 呵呵

4、其他几个问题有雷同,就不讲了,下面来个难度高的!!
//error C2906: 'const AFX_MSGMAP *CDlgInterface::GetThisMessageMap(void)' : explicit specialization requires 'template <>'
MFC的一个宏出了问题,说DIALOG_INST少了个template <>。
DIALOG_INST 定义如下:

#define DIALOG_INST(T, DLG) /
/
BEGIN_MESSAGE_MAP( CDlgInterface, CDialogPlus ) /
/*{{AFX_MSG_MAP(CDlgInterface)*/ /
ON_BN_CLICKED(IDC_Apply, OnApply) /
ON_WM_WINDOWPOSCHANGING() /
/*}}AFX_MSG_MAP*/ /
END_MESSAGE_MAP()

template <>应该放哪里呢?
查了查MSDN,区别不在DIALOG_INST的定义,继续往里深入,原来差在BEGIN_MESSAGE_MAP的定义。

#define BEGIN_MESSAGE_MAP(theClass, baseClass) /
PTM_WARNING_DISABLE /
const AFX_MSGMAP* theClass::GetMessageMap() const /
{ return GetThisMessageMap(); } /
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() /
{ /
typedef theClass ThisClass; /
typedef baseClass TheBaseClass; /
static const AFX_MSGMAP_ENTRY _messageEntries[] = /
{
改为
#define BEGIN_MESSAGE_MAP_TPL(theClass, baseClass) /
PTM_WARNING_DISABLE /
template <> const AFX_MSGMAP* theClass::GetMessageMap() const /
{ return GetThisMessageMap(); } /
template <> const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() /
{ /
typedef theClass ThisClass; /
typedef baseClass TheBaseClass; /
static const AFX_MSGMAP_ENTRY _messageEntries[] = /
{
DIALOG_INST重新定义一下:
#define DIALOG_INST(T, DLG) /
/
BEGIN_MESSAGE_MAP_TPL( CDlgInterface, CDialogPlus ) /
/*{{AFX_MSG_MAP(CDlgInterface)*/ /
ON_BN_CLICKED(IDC_Apply, OnApply) /
ON_WM_WINDOWPOSCHANGING() /
/*}}AFX_MSG_MAP*/

恩,就这样了。自己看看就知道了,mfc也在慢慢的改变,不过改动不大。

5、error C2039: 'ReadHuge' : is not a member of 'CFile,这个容易,readhuge早被read包括了。

6、还是mfc的问题
'static_cast' : cannot convert from 'void (__thiscall CCPMView::*)(WPARAM,LPARAM)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
定位到ON_MESSAGE(WM_USI_CREATE_DIALOG, OnUSICreateDialog)。

这是ms自己的问题,原来mfc对返回值要求不严,现在要求必须是LRESULT,只好用各函数调转一下。
用 ON_MESSAGE(WM_USI_SYS_STATEACTIVITY_CHANGE, OnSysStateActivityChange1)
代替 ON_MESSAGE(WM_USI_SYS_STATEACTIVITY_CHANGE, OnSysStateActivityChange)


LRESULT CCPMView::OnSysStateActivityChange1(WPARAM eSysState, LPARAM eSysActivity)
{
OnSysStateActivityChange((ESysState) eSysState,(ESysActivity) eSysActivity);
return 1;
}
来hook OnSysStateActivityChange一下,hook一下是最简单的办法,其他方法更绕远。

7、error C2593: 'operator +=' is ambiguous
定位到 m_strDist += iKey;
类型不匹配造成的,强制转换一下。 m_strDist = m_strDist + (char)iKey; OK!!

8、error C2514: 'LPCTSTR' : class has no constructors
定位到 bsStep.sLabel = LPCTSTR(*(m_aDialogStepData.pstLabel));
又是vc6不严格的问题,本来是想转换一下类型,结果LPCTSTR的定义由(typedef CONST CHAR *LPCSTR, *PCSTR;
)改变为(typedef __nullterminated CONST CHAR *LPCSTR, *PCSTR;
)。

那就强制一下好了,加个括号。bsStep.sLabel = (LPCTSTR)(*(m_aDialogStepData.pstLabel));

9、(CFrameWnd*)AfxGetMainWnd()出现了严重的问题。
没有出现编译错误的情况下,(CFrameWnd*)AfxGetMainWnd()返回空指针,我的工程是多线程的,多达20个线程一起跑,根本无法确定位置,其实这样的情况最烦人了,调试了将近两天才确定位置,幸好程序本身有很强大的日志系统,日志是多线程开发必须要考虑的部分。

10、内存溢出的问题。
内存溢出并不能总被发现,release下的正常情况,debug未必正常,这次就遇到了一个数组开小了的情况,vc6下也溢出了,不过居然没出错,vc8 下就不行了,总是内存越界提醒(bad pointer),只好一点一点找,最后发现了一个二维数组的问题,改了之后再没有错误了。

过了最后一关,整个移植就完成了,居然没什么错误,最后大家也不怪bill gate了。
很多类似的错误没有一一列举,希望大家触类旁通,多查查资料就好了。

三、一些技巧
1、可以vc6,vc8同时开着,有利于进行对比监控,经常是用f10一句一句运行对比,特别有利于调试错误数据。
2、用Beyond Compare 2对比vc6、vc8的工程,有利于发现不正确的修改。
3、多翻阅msdn,最好的参考就是msdn,把C2039编号直接检索一下,就知道是什么错误了,而且有很多如何修改的建议。
4、每天改动之前,先做备份,省得改错了。

四、总结
看来vc6移植到vc8可行性很好,这次大规模的移植证明了这一点。
移植的关键是对程序的理解,以前把vc6移植到BCB的时候基本上是做翻译的工作,好比英语翻译为汉语,只要理解了程序就好办,不过还是要感慨一下,微软作的很不错了,我这次移植基本上没遇到大的障碍,多亏微软了。

一个23万行代码的移植过程相关推荐

  1. 如何将三万行代码从Flow移植到TypeScript?

    作者 | David Gomes 译者 | 弯月 责编 | 郭芮 来源 |  CSDN(ID:CSDNnews) [编者按]在内存安全中,类型安全是很重要的一个命题.为了确保JavaScript项目运 ...

  2. 如何将三万行代码从 Flow 移植到 TypeScript?

    [CSDN编者按]在内存安全中,类型安全是很重要的一个命题.为了确保JavaScript项目运行的类型安全,本文的作者介绍了2016年时使用Flow的经历:由Facebook支持的Flow方案,不仅拥 ...

  3. Python逐块执行另一个Python程序中的代码观察运行过程

    今天是10月24日,也是一年一度的程序员节,祝所有热爱代码的朋友们节日快乐! 祝所有程序员1024节日快乐 全国高校教师Python课程高级研修班(线上,11月20-21日) 中国大学MOOC&quo ...

  4. 华为java一个月写多少行代码_[财经]阿里员工吐槽华为:面试官1万行代码都没写过? - 南方财富网...

    5月7日,有疑似阿里员工在社交网络上爆料称,打算跳槽华为,但是去面试后,真的是太失望,因为面试官真的是太水了. 从这位网友晒出的帖子看,一名阿里的员工面试华为云后端开发的岗位,但过程并不顺利,因为面试 ...

  5. 代码帝:一个月10万行代码 (只为存着膜拜)

    我所知道的一般程序员的代码效率在一个月 2K到5K之间吧!我所知道的,具体多少根据实现语言不同会有差异.这是统计出来的数据,当然不是不可能更高的代码效率,只是那样会导致 bug数量的成倍增加,当然还有 ...

  6. NDK/JNI demo ( 五 ) ORB_SLAM2在Android上的移植过程

    Android平台搭建和NDK环境配置 Android移植基础 NDK是集成的Android中调用C++代码的工具包,核心是JNI(Java Native Interface)技术,具体这里略过不表. ...

  7. 史上最烂的项目:苦撑 12 年,600 多万行代码!

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 来源:http://tinyurl.com/y55d23p4 转自:程序IT圈 这项目 ...

  8. 1个人70万行代码,20年持续更新,这款游戏号称开发到死,永不停更

    梦晨 博雯 发自 凹非寺 量子位 报道 | 公众号 QbitAI 这是一款「开发到死」,「永不停更」的游戏. 兄弟两人,一人开发,一人剧情,共同维持了这款游戏近20年. 现在的玩家刚刚打开它,往往会发 ...

  9. 我的天!史上最烂的项目:苦撑12年,600多万行代码...

    编译:欧剃 来源:projectfailures.wordpress.com 你见过最烂的项目,撑了多长时间才完蛋?六个月?一年?今天介绍的这个奇葩项目,不但一开始就烂得透透的,还硬撑了12年多,直到 ...

最新文章

  1. 性能提升-停用模块更新监控
  2. Mybatis执行select语句无匹配对象时返回集为Empty还是null
  3. 记录之关于tensoflow中使用Adam优化算法导致模型保存时参数的变化的记录
  4. Vagrant搭建可移动的PHP开发环境
  5. 程序员自家种水果,新鲜包邮配送
  6. asp.net尚未在web服务器上注册_最新版Web服务器项目详解 00 项目概述
  7. 使用C语言扩展Python(四)
  8. 软件测试mysql存储过程的用处实例_软件测试中实际应用:MySQL5存储过程编写
  9. mac配置VMware Fusion虚拟机网络配置
  10. [Google] 再见 SharedPreferences 拥抱 Jetpack DataStore
  11. 03-12306验证码文字 识别
  12. Either类java_通过实例学习Either 树和模式匹配
  13. iOS 解决:调用系统相册、相机是英文状态。
  14. -1 转换成二进制数是多少,负数左移右移。
  15. 搜狗二季度财报解读:有扎实的现在,也有性感的未来
  16. JQuery(js辅助开发类库)
  17. [ kvm ] 学习笔记 1:Linux 操作系统及虚拟化
  18. win2012故障转移mysql集群_Windows 2012 系统搭建高可用故障转移集群
  19. 阿里api文档链接地址
  20. 43 备忘录模式(详解版)

热门文章

  1. Neurology:肚子越大,脑子越小-肚子胖与大脑萎缩相关
  2. 环洋市场咨询:全球自动光学检测设备(AOI)收入预计2028年达到40.27亿美元
  3. mysql bitmap位图索引_PostgreSQL位图索引
  4. Unity--Floyd画出最短的路径
  5. 第一个android程序,qq农场助手
  6. mac下配置svn服务器详解及用户的权限管理(亲测)
  7. 你一定需要一款功能强大的图像批量处理软件
  8. 阿里旺旺出现create DOMDocument instance error
  9. 计算机局域网管理高级证书照片,局域网管理员中级证
  10. STM32的BLX R0