工作经验总结

2007.10.16


如何提高编译速度?


在DMR的开发中,出现了一个怪现象,每次编译的时候,编译一个文件的时间都好长,并且每个被编译的文件都要去连接BCG的Lib文件,这种编译速度简直无法忍受?


解决办法:在后面的分析中,发现我将Global.h这个头文件包含在Stdafx.h中了,并且Global.h这个文件是经常变的,程序中的大部分源文件都包含了Stdafx.h,Global.h的改动相当于Stdafx.h改动了,引起大部分的文件都需要重新编译。
所以,Stdafx.h应该包含的是经常或者说从来都不会变的头文件,比如afx.h,BCG等,一个字,包含不变的。
当把Global.h从Stdafx.h中移出之后,改动Global.h基本上不会引起很多的文件编译了,快了不少。但是,每个文件编译的时候还要去连接BCG库,并且速度也很慢,后面发现通过将Stdafx.h设置为预编译头文件后,编译文件的时候不会再去连接BCG库了,速度很快。


总结:
当使用了包含大量源代码的库时,比如MFC,BCG等,一定要使用预编译来提高编译速度。
预编译头文件(一般为Stdafx.h)中只能包含那些不变的头文件等东东,我们千万不要经常往Stdafx.h中加东西,比如头文件,全局变量等。


有一个好的办法是,将公共头文件(需经常改动的)按某些规则分解成多个头文件中,其他的源文件按需要包含各个小头文件,不要笼统地包含一个大头文件,否则因为头文件会经常变动,导致好多文件都需要重新编译。


扩展:
预编译原理:
Microsoft C 和 C++ 编译器提供了用于预编译任何 C 或 C++ 代码(包括内联代码)的选项。利用此性能特性,可以编译稳定的代码体,将已编译状态的代码存储在文件中,以及在随后的编译中,将预编译的代码与仍在开发的代码结合起来。由于不需要重新编译稳定代码,因此后面每次编译的速度都要快一些。 


加快编译速度


如果使编译速度更快,有以下几种办法:


1.减少 Visual C++ 必须为每个生成包含和检查的头文件数。
2.使用预编译头。有关更多信息,请参见 /Y(预编译头)。
我的总结中就是这两点!


3.当直接调用 cl.exe 时,不要为每个源文件各调用一次编译器;在同一个调用中将所有源文件传递到 cl.exe 以创建 .obj 文件。
4.使用最小重新生成;有关更多信息,请参见 /Gm。
5.使用增量链接;有关更多信息,请参见 /INCREMENTAL。
这3个一般都是编译器的默认选项,我们也不会改,所以不是重点。


6.合适的时候,使用 #pragma once。例如,如果头文件使用包含保护。
这项一般我们都做了或者使用包含保护了。


7.动态链接到 CRT;有关更多信息,请参见 /MD。
一般都是这样,并且可能对编译速度的影响不大。







2007.12.11
今天在弄那个告警信息对话框的时候,才发现动态创建控件自己设置属性很不好搞,总是设置不对,所以,以后尽量少动态创建控件,直接往对话框框上拖还好些。


2007.12.12 
今天在修改刘雪花的告警时又遇到了告警级别和描述等等被CAlarmView和CAlarmListCtrl使用的情况,所以关于这些的定义放在什么地方都不合适,我觉得最合适的地方是另外建一个AlarmDef.h的文件,专门用来放这些定义,情况可能会比较合理些,应该是这样,以后我就这样搞。


2008.06.02
如果非主线程中牵涉到了界面,要特别小心了,比如我的Output窗口,本来感觉没问题,但是好像偶尔出现过一次,当用户改变光标位置时,新来的内容插入到中间去了。经过仔细分析,感觉是Output中有个别语句并不能占据主线程,当Output所在线程切换到主线程时,用户就可以参与了,等再回来时状态已经发生变化了,导致出错。
经验总结:和界面相关的计算代码必须和界面函数严格绑定在一起,比如让将它们放在一个SendMessage的处理函数中,这样只要一进这个函数,主线程就一直被占用,不会再被抢占了!!!


2008.06.10
当map的key是一个结构体时,必须重载==操作符,全局的也可以,或者是友元函数,否则编译不能通过,今天时间来不及,没有试(判断是否是同一次统计),现在终于验证了一下:
struct TEST
{
friend bool operator<(const TEST& t1, const TEST& t2)
{
//实现比较
}


int i;
int j;
};


或者
bool operator<(const TEST& t1, const TEST& t2)
{
//实现比较
}


这样后,就可以使用了,如下:
map<TEST, int> mapTest;
TEST t;
mapTest[t] = 3;


2008.06.24
今天调试代码时发现列表中有空行,以为是SendMessage引起的多线程问题,还有点怀疑以前对SendMessage的看法,晚上回来试验后,确认了以前的看法是对的,即只要是通过SendMessage,PostMessage等函数发送的消息,必定都是在主线程中处理的,不会出现多线程问题!!!


2008.06.28
对于ifstream类,一定要传入UNICODE版本的路径字符串,因为在内部,负责将多字节字符串转换为UNICODE字符串的函数有缺陷,不能正确将中文路径的多字节字符串转换为正确的UNICODE字符串(它仅仅是在每个字节前加一个字节0),导致打开文件失败。


经常遇到断点不能生效,很烦人,一般可以按MSDN上的办法解决问题:
工具->选项->调试->常规->取消"要求源文件与原始版本完全匹配"


2008.07.07
在release下,如果出现字节对齐问题,由系统填补的数据是随机的,不要以为都是填成一样的。而在debug下,它都会填成一样的,所以,有时会出现debug对,而release错的情况。比如信令统计


2008.07.08
在调用TerminateThread结束线程后,线程调试窗口中还会继续显示被杀掉的线程,不知道为什么?是线程没有立即销毁呢,还是线程调试窗口没有立刻刷新?


2008.08.15 晴 星期五
窗口之间最好采用消息通知方式进行处理,不要在一个函数中控制多个窗口的界面处理,比如TCE,否则当某个窗口关闭时,或者某个窗口的界面发生变化时,需要到处加判断,或不能适应变化。
一种可能的解决办法是
窗口采用注册,反注册到逻辑处理层的方式,等逻辑处理完了之后再根据注册的窗口一一通知界面,界面自己进行刷新。


目前TCE的Action就相当于逻辑处理层,但受累于窗口没有存在在结构体中,不能遍历发送消息(其实也可以写成函数)。如果采用上面的办法,消息的定义就显得非常重要,最好能简单,统一,虽然树的操作无非就添加,删除,更新项,但是从这可以衍生出很多处理,比如导入时先删除所有子节点,再插入子节点,像这种消息该如何定义?对于Cell也一样道理


2008.08.15
当你想包装一个类的时候,比如你想限制CTreeCtrl的某些函数,比如在InsertItem做一些特别的操作,采用包含比采用继承要好得多,包装后你可以把接口限制的死死的,没提供的功能外面就用不了,可以完全控制,而继承就很难实现这种控制,因为父类的public函数,你想让外界不能访问是很难的,包含就很容易,呵呵!


2008.08.18 
总是不能注册,虽然用Dependence查看不缺少什么文件,但一般情况下都是因为有些依赖的模块没有在本地编译引起的,即debug的东东只能在本地编译,最好不要拷贝用。


2008.4.21
今天看了一下MSDN中的DLL部分,知道有很多种DLL,输出函数的方式也有多种,晚上在家又看到多线程编程,也有很多方法,还有就是女朋友花这么长的时间来确定将要托付终生的男人,可以得出以下结论:
专家不是仅仅会实现某件事情,而是会从多种实现方法中选择最适合的方法来实现。


今天看了一天的DLL,才知道DLL中还有那么多东西不知道,我怎么能够做到最好呢,其实MSDN就是一部技术百科全书,搞透彻了,比看多少书都有效果。


2008.07.31
在导入Linux下的动作库之前,必须先导入Windows下的动作库,这看起来是一个很别扭的做法,但是,用户却接受了,所以,有时别扭并不代表不好,别扭是从技术人员的角度出发的,而从用户的角度出发,先导入Windows下的动作库并不是一件麻烦的事。
遇到问题,最好的解决办法是和别人沟通,达成一致,不要简单地从纯技术角度考虑。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值