yaodong

yaodong
随笔 - 20, 评论 - 367, 引用 - 53

导航

标签

每月存档

最新留言

广告

【第1页/共2页,25条】
首页
前页
1
2007年12月24日

关于雷军同学有趣往事

1. 雷老虎
雷军的第一个孩子出生了,是个女儿,公司同事们刚刚得知这个消息后就在内部新闻组发起了起名活动。很多人给出了女孩名字的建议,最后通过投票,最高得票的名字是“雷婷婷”。这个名字是有典故的,李连杰的电影《方世玉》中,女主角就叫“雷婷婷”(李嘉欣饰演),而她爸爸叫“雷老虎”,雷老虎的名言是“以德服人”。当然这是一个员工的集体玩笑而已,雷军没有采用这个名字。

2. 性格
雷军的性格争强好胜,追求完美,控制欲望强烈,有点象《六人行》里面的莫妮卡,雷军会关心公司的窗帘是不是完好,清洁工有没有弄干净地板。在任何对抗性游戏中,哪怕只是公司内部纯粹娱乐性质的游戏中也会努力争取胜利。雷军很聪明,也还算强壮,一般的都是能赢的。当然也有例外,比如某次乒乓球比赛遇到了高手,是个市场部经理,雷军的表情明显郁闷了。有次公司庆祝新年的晚会,几个人一起做游戏,第一次雷军输了,比第一名差了一点点,在他的强烈要求下,再来了一次,结果他赢了,但是其他人绝对没有故意防水。

3. 侃
雷军极其健谈,而且有强烈的表达欲望,只要他有时间总会拉一些员工朋友一起聊天,虽然工作是聊天的主题,但是经常被他的跳跃思维带得离题万里,还好他是会意识到这一点还会及时把话题带回来。和雷军聊天可以长见识,他可是中国IT业的老革命了,业界的陈年往事最近的八卦新闻,你都可以从他那里听到。如果你晚上10-11点左右被雷军抓住聊天,那么你最好给家里个电话说今天不回去了。

4. 上市
我第一次听到金山公司打算上市的消息,是从雷军那里听到的,那是1998年的11月。当然那时上市只是遥远的梦想,金山当时距离世界上最宽松的上市条件还差非常远。

5. 勤奋
雷军的日程表就没有所谓加班 7×12 是基本工作时间。大部分节假日都会被会议占据。金山有很多勤奋的员工,但是总体来看论勤奋10多年来雷军绝对高居榜首。每年的10月-11月一般是词霸发布新版本的日子,99年的十一国庆雷军陪开发组加班,亲自做测试帮助修改词库数据,3年后才第一次出现没有加班的国庆节。

6. 例会
早期金山人很少,北京才30多个人,每周一早上全体员工例会,雷军主持站着开会,各个部门经理汇报上周工作和下周计划,有部门合作方面的问题当场沟通解决。这样的全体例会一直开到公司员工超过70人才取消,改成各部门分别开例会,然后部门经理开例会。这样的例会成为传统,此后各个部门例会也都是这样开的。

7. 演讲
雷军的演讲很具有感染力的,每年的几次中层经理会都会有他的演讲,主题多围绕公司的总结和下一步战略。雷军还会刻意培养甚至要求其他人的演讲技巧,尤其是中层,在金山做中层没有本事在几十人面前慷慨激扬的发表一番演说是混不下去的。

曾经在金山任职的人或多或少都受到雷军的影响,从他身上学到一些东西。如果金山是所学校,雷军无疑就是校长。
雷军的离去标志着中国IT业的理想时代终结了,进入了完全由资本驱动的时代,至少我是这么认为的。

posted on 2007-12-24 19:38:00 by yaodong  评论(6) 阅读(4829)

 
2007年07月13日

Symbian 中也有类似Windows COM的机制,用来作为二进制的模块间接口标准。
ECom比起windows COM来要简单得多,没有GUID 没有IUnknown,没有marshal,没有其他好多东西。。。

那么,,,还剩下什么呢?逐个说一下

首先 和COM一样你的DLL要注册,这样别人才能找到你,不同的是,不是注册到注册表,DLL也没有引出注
册反注册的函数(没有类似DllRegisterServer and DllUnregisterServer的东西),而是写一个RSS文件,
里面写上你的ECom的注册信息,这个RSS文件编译后生成RSC文件,放到系统的ECom插件注册目录下,这样
系统就可以通过这个文件中的信息找到你的ECom DLL.这个RSS不难写,基本上抄一个改个ID就好了。
唯一要注意的是,RSS编译后产生的RSC文件名要和DLL文件名一样。

*注意: 这里的RSS和Blog那个rss不是一个概念,Symbian 里面的资源文件的展名就是RSS。

然后,你的DLL必须实现一个引出函数
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount);
这是必须的,这个函数返回一个结构数组,描述了这个DLL所包含的所有对象的ID 和 工厂函数的指针。
通常这个函数是返回一个DLL里的全局变量比如:
const TImplementationProxy ImplementationTable[] =
    {
    IMPLEMENTATION_PROXY_ENTRY(0x13457890, CFoo::NewL)
    };

CFoo::NewL会返回一个,CFoo*,而CFoo一定是实现了 ID 0x13457890 对应的接口。

就是这么简单,和Windows的COM比起来非常原始,但是ECom在Symbian 和 S60里面应用非常广泛。
因为手机系统需要极强的定制能力,大多数功能都是靠ECom实现的,不同版本的差异很多是靠发行
的时候采用不同的ECom来做的。ECom的DLL在制作成手机的ROM的时候和其他一般的DLL是有些不
一样的,ECom会拥有一个单独的区域,并且编制索引来保证ECom的加载会比其他DLL要快一些。
所以有些时候会把一些数据文件做成ECom,就是因为加载比较快。

最后借这里放个招聘广告,如果你对于手机平台,Symbian 系统开发有兴趣,想深入了解S60,甚至希望
参与到S60的设计和开发,或者对于s60相关的项目管理有兴趣。现在有个不错的工作机会,不要求你有
Symbian或者手机平台的开发经验,但需要你对技术有热情。

Software Engineer
http://careers.nokia.com/nokia/hr/recrsyst.nsf/WB2RR/C31D75074228F5F6C22572BF0028BCAD?OpenDocument&Lang=Global

Project Manager
http://careers.nokia.com/nokia/hr/recrsyst.nsf/WB2RR/749DDCA528A35375C22572BF00285178?OpenDocument&Lang=Global

posted on 2007-07-13 16:10:00 by yaodong  评论(2) 阅读(6698)

 
2007年04月04日

google拼音真的不错,尤其是词库中有很多常用词汇,词表的优先级设计也不错,基本常用的都在第一个。
最让我感动的是,收录了很多魔兽世界游戏的词汇,魔兽里面太多的音译词汇了,平时输入很麻烦,所以只好用
缩写代替,比如STSM 斯坦索姆,TL通灵学院,BWL黑翼之巢等。还是不方便,对于新手往往要给他解释一遍缩写。

此前我是微软拼音的忠实用户,用了很多年了。
微软的拼音的优点是,兼容性好,易用性也不错,就是词库没有与时俱进
微软的IME framework 太复杂,我也曾经写过IME程序,做一个能兼容所有程序的输入法真不容易。
市面上的输入法多少都存在一些兼容性问题。

google拼音目前我还没发现兼容问题,而且词库丰富,对于整句输入,首字母输入判断也算比较智能。
现在已经代替微软拼音成为我的默认输入法了。

微软拼音多年来没什么对手,也就一直没什么重大的改进,现在估计感到竞争的压力了吧?

posted on 2007-04-04 15:29:00 by yaodong  评论(29) 阅读(8040)

 
2007年03月29日

RArray类,属于symbian OS提供的基础容器类,并且是比较重要和常用的一个。

如果从名字来看这是一个数据类,功能貌似和 MFC的CArray,stl的vector差不多吧?
如果这么想就错了,RArray是个泛型数组容器类,但是功能比CArray vector 提供的要多。

尤其是他提供的排序和查找功能,其实现方法比较诡异,对初学者来说容易造成迷惑。
个人认为这个设计比较蹩脚,至于为什么会这样,我想不出,已经写信给作者咨询了,不过还没得到答复。

RArray的排序是这样的,它规定数组中每个元素可以有一个 order key,这个order key其实就是数组元素的某4个字节
至于具体是哪4个字节作为order key是由key offset决定的,key offset 是构造函数的参数,是可选的,默认为0

就是说,默认情况下,数组里面每个元素的前4个字节会被用来作为排序的key。
因此RArray也规定,每个元素至少要有4个字节,并且大小必须是4个倍数,否则某些函数不能用,甚至会产生异常。

比如我们声明一个 结构体 Bar 作为数组的元素,然后构建一个Bar的数组 barArray

struct Bar
{
   TInt  iId;
   TInt  iSize;
}

RArray<Bar> barArray;

于是 iId就会成为order key了,因为默认情况下key offset 为0,iId就是元素的头4个字节。
如果你要用isize做order key,那么只要指定key offset为4就好了。

如果需要RArray的排序功能那么 你就需要用到一系列名字中带有KeyOrder的函数比如 InsertInSignedKeyOrderL,FindInSignedKeyOrderL等等

Insert操作时,会按照插入元素的order key排序来查找合适的Insert位置。
Find时,也是比较order key,由于查找时只比较order key,所以会写出这样有点诡异的代码
比如我们要查找 iId 为 100的元素的位置
Bar foo;
foo.iId = 100;
TInt index = barArray.InsertInSignedKeyOrderL(foo);
查找条件中的 iSize没有初值?对没有,也没必要,因为InsertInSignedKeyOrderL只比较前4个字节
iSize用不到,所以也不用给初值。

注意 函数名中的 Signed,还有与之对应的 Unsigned,这些表示比较order key的时候是否考虑符号。
就是order key是 当作TInt还是TUint来比较。

如果你不用这些带有KeyOrder的系列函数,那么和一个CArray的数组基本一样。

另外 RArray有2个特化版本,RArray<TInt>,RArray<TUint>,可能是为了提高效率吧。

现在我明白Symbian 里为什么没有 list map 等容器类了,RArray实在是一专多能。
不过我还是认为这样的设计不够优雅,也许作者有苦衷?希望RArray作者的答复里可以给我解释。

posted on 2007-03-29 17:13:00 by yaodong  评论(25) 阅读(6509)

 
2007年03月26日

理解 ActiveObject

ActiveObject 在symbian里是一个很重要的概念
应该说所有的Symbian程序都是运行在一个或多个ActiveObject里面。

大多数Symbian的程序的入口几乎都是这样的,除了少数Console程序以外
GLDEF_C TInt E32Main()
{
 return EikStart::RunApplication( NewApplication );
}

如果你有机会调试并跟踪到Symbian的源代码里面,你会发现EikStart::RunApplication会调用
CActiveScheduler::Start()

这个调用意味着启动了一个 Scheduler 也就意味着进入了 ActiveScheduler的循环。

程序运行进入CActiveScheduler::Start()之后就不会出来了,直到程序结束。

这似乎很象什么?对了,象windows的消息循环!

while(getmessage(...))
{
 TranslateMessage(...);
 DispatchMessage(...);
}

除非程序退出,否则会一直运行在这样的死循环里面。

Scheduler::Start里面也是类似的代码,做着类似的事情
1。等待事件
2。找一个合适的对象来处理事件
3。然后继续等待事件,直到得到一个退出的事件。

但是和windows的消息循环不一样的地方在于,Scheduler 里面调度的不是窗口
而是一个个ActiveObject,Scheduler获得了一个事件后,就会找一个合适的ActiveObject去处理事件

所有的ActiveObject在创建后会通过CActiveScheduler::Add 把自己加入到Scheduler里面。

这套模式又使我想起了什么,对了,是ACE--那个网络程序的framework,ACE中也是类似的模式
不过Scheduler叫做Reactor。
不过ActiveObject叫做Task。

本质上讲,这就是一套用单线程通过事件驱动,来模拟多任务的设计模式。
每个ActiveObject是独立的,多个ActiveOject看似是并行的,实际上却是运行在一个线程里。

不同的是ACE里面的 Reactor 是可以多线程的,可以用一个线程池来同时执行多个 Task。

在symbian的世界里,设备的资源都很有限,内存小,CPU也慢,所以开一个线程开销比较大,ActiveObject有效的
代替了部分多线程的功能。

编写ActiveObject还是比较简单的,所有的ActiveObject都是从CActive派生的。
其中RunL、DoCancel 是必须重载的虚函数,每次有事件发生Scheduler就会调用RunL
那么如果有多个ActiveObject存在,那么事件发生了Scheduler怎么才能知道该调用哪个ActiveObject呢?

很简单,每个ActiveObject都有一个iStatus成员,每个事件发生器都会指定一个iStatus,Scheduler会调用
iStatus对应的那个ActiveObject。

比如最简单事件发生器,RTimer,他的作用是在指定的时间后产生一个事件,起到定时器的作用
用法如下
RTimer t;
t.After(iStatus, 1000000);

上面的语句表示在1秒钟后 产生事件,这个事件将由iStatus对应的ActiveObject来响应。(Symbian系统下 时间单位是 1/1000000 秒,而不是1/1000秒)

 

posted on 2007-03-26 17:12:00 by yaodong  评论(2) 阅读(2132)

 
2007年03月22日

Windows的庞大和臃肿是早有体会的了,最近作Symbian开发

别以为Symbian是个小东西,我得到的统计
Symbian & s60 源代码包括 10万个左右文件,总共1G左右的大小。但这还不是全部源代码,某些内核,本地化资源的内容没有计算在内。

在手机和PDA上系统的Release版本也不过几M的样子,源代码是Release的几百倍。由此推算windows的源代码要以TB计算了。

在现在的软件开发和设计模式下,代码膨胀是不可避免的,能写出简练精巧的代码的人是极少数,其他大部分是写臃肿丑陋的代码的庸才,但是需要实现功能那么多,靠少数高手是根本干不完的。

另外需求变化很快,新的需求出现,原有的设计通常无法满足,只有在上面修修补补,经常可以看到代码中无数复杂嵌套的If ...else... ,重构的代价是高昂的,尤其在Weekly build 甚至Daily build的压力下,很少会冒险去动原有的可以测试通过的代码。

对于管理者来说,他们很清楚这样下去产品终究会走上绝路,但是他们会极力避免发生在自己的任期上。

我有时想,软件产品就像生命一样,也会经历生老病死的轮回。

最后做个推荐,我发现博客堂只有放在首页的随笔才会访问量比较高,文章就差很多了

写了篇关于 Symbian 两次构造 NewL NewLC ConstructL 的文章,有兴趣的去看看吧。
http://blog.joycode.com/yaodong/articles/94824.aspx

posted on 2007-03-22 11:27:00 by yaodong  评论(18) 阅读(6128)

 
2007年03月06日

理解 NewL ConstructL NewLC ELeave

初学Symbian开发,第一件感觉迷惑的事情是CleanupStack 第二件肯定是随处可见的NewL,NewLC,ConstructL。
这些函数的出现依然和内存泄漏有关,这是一种被称为两步构造的机制,英文叫Two-phase Construction。
我知道C++里面的 new 操作符实际上完成2件事,第一根据对象类的大小在堆上分配一块内存并获得指向内存的
指针,第二利用指针调用类的构造函数,最后把指针返回。

在Symbian上这样做是有隐患的,就是当你分配好了内存,但是调用构造函数的时候程序意外退出了,这样会造成
刚才分配的内存产生泄漏。只有那些放入CleanupStack的内存,在程序意外结束后会被释放,new 分配的内存在
调用构造函数之前还没有被放入CleanupStack呢。

Symbian的设计师为了解决这个问题,给所有开发者设计了一个编写程序的定式,这就是Two-phase Construction

具体是这样的:

把普通的new 操作分为2个步骤来进行,第一步只分配内存,当分配的内存被放入cleanupstack后,第二步进行构造。
但是在C++里 如何阻止编译器的new操作不调用构造函数呢?这个貌似不可以。。。
于是Symbian的设计者作了个规定,类在构造函数里不要做任何可能产生异常的操作,只能做那些绝对安全的事情,比如
简单的变量赋值,然后提供一个名字叫 ConstructL的函数,在这个函数里做所有类的初始化工作,当然包括那些危险
的可能导致异常的操作。

那么 Symbian的 类构造就变成了这样
比如 有一个叫 CFoo 的类,我想声明一个指针 p,创建一个CFoo的对象赋给 p
CFoo *p = new(ELeave) CFoo();
CleanupStack::PushL(p);
p->ConstructL();
CleanupStack::Pop();

这样写是不是有点太罗嗦?每个对象都要用4条语句创建,如果是频繁使用实在是太麻烦了。
于是Symbian的设计者又作了一个规定,每个类要实现一个NewL的static函数来完成上面的4条语句的工作
class CFoo
{
public:
 static CFoo *NewL()
 {
  CFoo *self = new(ELeave) CFoo();
  CleanupStack::PushL(self);
  self->ConstructL();
  CleanupStack::Pop();
  return self;
 }
}

有了NewL以后,调用CFoo的类的程序简化了
CFoo *p = CFoo::NewL();

那么NewLC又是什么呢?和NewL有什么不同?
有些类是这样的,他们提供一些方法,需要在对象创建完成后执行,但是这些方法也是会产生异常的比如
CFoo 如果有一个方法叫 DoSomethingL()

那么程序可以这样写吗?
CFoo *p = CFoo::NewL();
p->DoSomethingL();

显然这样写是有问题的正确的写法是
CFoo *p = CFoo::NewL();
CleanupStack::PushL(p);
p->DoSomethingL();
CleanupStack::Pop();

天啊,又是4条语句,太麻烦了。要知道在NewL结尾我们刚刚把CFoo的指针从CleanupStack里拿出来,马上就又放了进去。
是不是可以简化呢,那好我们再节约2条语句
NewL去掉结尾的CleanupStack::Pop();
 static CFoo *NewL()
 {
  CFoo *self = new(ELeave) CFoo();
  CleanupStack::PushL(self);
  self->ConstructL();
  return self;
 }
调用去掉CleanupStack::PushL
CFoo *p = CFoo::NewL();
p->DoSomethingL();
CleanupStack::Pop();

Symbian的设计者又规定了,具有以上行为的NewL 应该叫NewLC。表示指针返回后,没有从CleanupStack里取出,你可以继续调用一个危险的操作,在最后调用CleanupStack::Pop();

我发现 NewL 可以通过调用NewLC实现。
那么一个符合Symbian设计师的N条规定的类应该这样写

class CFoo
{
public:
 static CFoo *NewLC()
 {
  CFoo *self = new(ELeave) CFoo();
  CleanupStack::PushL(self);
  self->ConstructL();
  return self;
 }

 static CFoo *NewL()
 {
  CFoo *self = NewLC();
  CleanupStack::Pop();
  return self;
 }

 virtual ~CFoo()
 {
 }

protected:
 CFoo()
 {
 }

 void ConstructL()
 {
 // ....
 }
}

这里注意 CFoo的构造函数不能是Public的,为了防止使用者用new 或者在栈上创建对象。
析构函数要写成虚函数,这是纯C++问题,不明白的去看 More Effective C++

要说明一下,以上的写法是Symbian极力推荐的,但是不是硬性规定的,你只要保证没有内存泄漏
可以不这么写。
我个人还是推荐这样,这样的代码写Symbian程序的人都可以很好地理解。

最后说一下 new 之后为什么要有一个 (ELeave)。
new操作符是被Symbian重载过了,ELeave是给new的一个参数,他的意思是告诉new当无法分配内存时
程序就退出。比如内存不足的时候。

所以我们用了ELeave的话 就不用检查new 返回的指针了,能返回就一定是对的
如果出了错程序就结束掉了,new根本就不会返回。

NewL NewLC 是Symbian程序标志性的函数,所以有个Symbian开发的资源站点就叫 www.newlc.com

posted on 2007-03-06 11:18:00 by yaodong  评论(9) 阅读(4226)

 
2007年03月02日

听说开发Symbian程序,首要的也是最重要的之一,就是搞清楚CleanupStack
CleanupStack 用起来貌似很简单,我写了如下代码:

假设我有一个叫 CFoo的类

CFoo *p = new (ELeave) CFoo();
CleanupStack::PushL(p);
// 使用 p 作一些事情,例如调用 p->SomeFunctionL();
// ....
CleanupStack::Pop();
delete p;

我不禁疑问为什么要这样?Windows程序从来没有这样的代码,DOS都没有,Linux貌似也没有。
Symbian这样做是为什么?相信所有开始学习Symbian的人都会有这样的疑问。

我看了一下Symbian OS的一些介绍和历史,了解到Symbian OS从开始就是针对移动设备,主要是手机PDA所
设计开发的操作系统,设计上对于资源消耗,效率和安全稳定性都比较看重。
移动设备的主要特点就是,运算能力差,内存小,需要长时间运行,有时需要长达N年。
Symbian还是一个多任务系统,多个进程共享系统内存。
Symbian还是一个开放的平台,提供开发工具和接口,允许任何人为它开发软件。

在这样的情况下,内存泄漏是一种需要极力避免的错误,由于运行时间长,哪怕一点点内存泄漏也会
随着时间增长吞噬掉系统的本来就不多的内存,从而造成系统崩溃。


=====================回忆的分割线==========================================

我回顾了一下微软体系下是怎么解决内存泄漏的

C语言时代,完全没有解决办法,一切都靠程序员自己提高警惕,小心处理所有的内存分配和释放。
那个时代,高手和一般程序员之间的差别是很大的,能够驾驭大型的程序,小心控制好内存和指针,需要
高超的技巧和丰富的经验。好在DOS也不需要太稳定,每天都重新启动N次也无所谓。

C++语言,增加了对象的概念,有结构化异常处理,给程序员提供了一种可以控制内存的方法。
我们可以把内存释放放在类的析构函数里,这样就不会被忘掉,也可以用智能指针模板类比如 std::auto_ptr来
包装指针。如果程序可能意外退出,那么我们可以用结构化异常处理,捕获异常,我们仍然有机会在程序结束前释
放掉内存。我可以用容器类来存放数据,避免自己分配和管理内存。

到了windows时代,有了进程地址空间的概念,即使一个进程意外结束,即使有大量的内存泄漏,当进程结束后
所有这个进程的内存都会被释放掉,甚至包括进程用到的内核对象和系统资源都会被释放。而且随着PC硬件的发
展,内存变得很大,一些小的内存泄漏几乎不会产生什么问题,在积累到足以导致系统崩溃前,通常进程就结束掉了。

即使如此,内存泄露仍然是个大问题,尤其是对于一些企业级应用,服务性程序,需要长时间运行,内存泄漏的
积累会造成大麻烦,所以产生了很多工具和类库,工具可以用来监测内存泄漏,帮助开发者找出问题,类库封装
了很多系统服务和内存管理,让开发者避免和内存直接打交道。

只要是人就会出错,总会在某个时候疏忽一下忘记释放。如果成本允许,那么可以靠大量的测试来防止。
以上的方法并没有从根本上解决问题,虽然我近几年已经很少出内存泄漏错误了,但也不是绝对没有。

Java的出现,是一个重大转变,delete这个关键字彻底消失了,只有new保留了下来,内存的释放被垃圾回收机制
代替了,从此开发人员不用关心内存的释放了,一切都交给系统去处理,后来的C#也是类似的机制。


===========================回归的分割线========================================

似乎有点扯远了,回到Symbian,我在想为什么Symbian没有采用以上的方法呢?
Symbian本身是使用C++编写的,开发语言也主要是C++,虽然也支持Java和其他一些脚本语言,但是有些程序必须用C++来
开发,平台的API几乎都是C++接口的。Java的虚拟机,脚本的解释器总是要用C++来编写的。所以C++是唯一的选择。
完全用Java 和 C#来开发肯定不可能。

那么提供一个类库来解决内存分配释放呢?事实上这样的类是有的,但是只能解决开发人员忘记释放的问题,对于程序
意外结束仍然没有办法。

那么异常处理呢?很遗憾,一篇文档上说在Symbian开始设计开发的时代,还是上个世纪90年代的事,那时候C++编译器还不能完全
支持C++异常处理,至少Symbian 的编译器GCC 不可以。

我估计最后Symbian 的设计者选择了一个看似不够优雅,但是却是无可奈何的选择,那就是CleanupStack。

这个方案基本是异常的机制的替代品,大致是这样的
程序创建一个 Stack(栈),分配的内存的指针会被通过调用 CleanupStack::PushL(..) 放到Stack里。
释放内存之前 调用 CleanupStack::Pop() 把指针从stack中取出。
另外我们经常会看到 TRAP(。。。) 宏,你可以简单地认为相当于 try...catch... ,出现异常的时候会获得错误码。
所以要把一些危险的函数调用放到TRAP里面。(如果以后有机会我打算详细写写TRAP)

那么如果在new 和 delete之间产生了异常,那么内存指针就会保留在stack里,系统在进程结束的时候会把Stack里面
的内存释放掉。这样保证了即使程序意外结束,也不会有内存泄漏。

这样的方案是不是足够好呢?如果开发人员忘记了PushL或者Pop怎么办?不是一样会有内存泄漏吗?
开发人员记性不好的确是个大麻烦,但是有很多工具可以帮你检测问题,比如CodeScanner PC-Lint等等,如果你连使用工具
都忘掉了,我就无语了。。。

CodeScanner是个好东西,专门为了Symbian C++开发的静态代码分析工具。可以给出详细的关于代码问题的报告。
CodeScanner:http://www.mobileinnovation.co.uk

看来我只要保证了 PushL和Pop匹配,所有的内存分配都会被记录下来,程序结束之前都会被释放掉。

posted on 2007-03-02 14:53:00 by yaodong  评论(5) 阅读(7485)

 
2007年03月01日

最近2年生活过的很动荡,主要是家庭的原因,每隔几个月就有些变化,现在总算稳定下来了。
和技术也有些疏远,可以看到我的blog 两年来都没什么更新,这里要感谢开心同学没有把我的帐号删掉

最近作了一个重要的决定,就是告别PC & windows开发,转向移动和潜入式平台,比如Symbian.
此前几乎没有Symbian 开发经验,一切从头开始,再次回到helloworld,就像我写第一个Turbo C程序那样。
虽然Symbian 也是用C++开发,但是却有很大不同。

今后我会写一些学习的感悟,以及经验和技巧与大家分享。

带着我10年的微软平台的开发经验去观察 Symbian 的世界,我尽量用Windows 的概念通过类比,去解释Symbian的问题。相信会对其他从Windows转向Symbian的人有所帮助。

posted on 2007-03-01 11:27:00 by yaodong  评论(10) 阅读(6928)

 
2005年10月06日

类似eMule的方式,在网站上写一个 ed2k://XXXXXXX, 这样的HyperLink,就可以启动自己的程序。

和简单,在注册表HKEY_CLASSES_ROOT下创建自己协议名的项

比如 myp 让后在 HKEY_CLASSES_ROOT\myp 下创建一个字符串键值

URL Protocol,值为空串。这个很重要,表明这是一个协议名称。

然后创建HKEY_CLASSES_ROOT\myp\shell\open\command 默认值写为:

"你的程序绝对路径" "%1"

比如  "C:\Program Files\myproduct\myproduct.exe" "%1"

这样当有人点击或运行 myp://xxxxx 的url时就会启动你的程序,并且把url作为第一个命令行参数。

posted on 2005-10-06 13:22:00 by yaodong  评论(13) 阅读(5203)

 
2005年07月27日

微软在XP sp2中对单个进程同时发起的连接尝试做了限制,最多10个。

这个限制不是限制连接数,只是限制连接尝试

详情参见 Event 4226, EVENT_TCPIP_TCP_CONNECT_LIMIT_REACHED

在命令行窗口下输入  netstat -no可以看到当前所有TCP连接的状态。
那些显示为 SYN_SENT 的就是在试图建立连接。这样的Socket最多限制为10个。其实对于一般的软件没什么影响,影响比较大的是那些P2P软件。P2P就是
靠不断建立连接,来在其他客户端搜寻自己需要的数据的。由于这个限制P2P客
户端在单位时间内能连接的Peer就很有限,大大影响了下载速度。

解决的方法是:

关掉windows 防火墙,这个需要用户来做
另外就是用一个修改过的tcpip.sys替换系统文件。
可以在下面网站下载
http://www.lvllord.de/

posted on 2005-07-27 21:58:00 by yaodong  评论(9) 阅读(7643)

 
2005年01月06日

最近一直在.NET,偶尔发现boost 1.32已经发布了一段时间

虽然只是提升了0.01变化还是很大的

比如:

编译变得很简单,如果懒得设置,只要输入 bjam stage  即可编译成功
支持了静态连接,使用起来很方便,使用boost不用带着很多dll发布了
增加了 读写锁,.NET里就有读写锁,但是我觉得boost的更好用
另外还有很多改进,我正在研究中。。

期待boost的某些特性尽快被纳入C++标准

posted on 2005-01-06 22:09:00 by yaodong  评论(15) 阅读(8696)

 
2004年12月26日

添加对System.Management的引用

using System.Management;
。。。
//获取IP,子网掩码(subnet mask)和默认网关
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
   ManagementObjectCollection nics = mc.GetInstances();
   foreach(ManagementObject nic in nics)
   {
                if(Convert.ToBoolean(nic["ipEnabled"]) == true)
    {
     Console.WriteLine((nic["IPAddress"] as String[])[0]);
     Console.WriteLine((nic["IPSubnet"] as String[])[0]);
     Console.WriteLine((nic["DefaultIPGateway"] as String[])[0]);
    }
   }
。。。

如果还需要其他信息参考 Platform SDK: Windows Management Instrumentation

posted on 2004-12-26 20:17:00 by yaodong  评论(44) 阅读(25644)

 
2004年12月18日

2004年12月,联想17.5亿美元收购IBM全球PC业务

2004年12月,赛门铁克135亿美元收购Veritas

2004年12月,Oracle公司103亿美元收购PeopleSoft

To be continue...

posted on 2004-12-18 13:49:00 by yaodong  评论(16) 阅读(4294)

 
2004年11月26日

一般的windows 复杂的界面需要使用多层窗口而且要用贴图来美化,所以不可避免在窗口移动或者改变大小的时候出现闪烁。

先来谈谈闪烁产生的原因

原因一:
如果熟悉显卡原理的话,调用GDI函数向屏幕输出的时候并不是立刻就显示在屏幕
上只是写到了显存里,而显卡每隔一段时间把显存的内容输出到屏幕上,这就是刷新周期。

一般显卡的刷新周期是 1/80秒左右,具体数字可以自己设置的。

这样问题就来了,一般画图都是先画背景色,然后再把内容画上去,如果这两次操作不在同一个
刷新周期内完成,那么给人的视觉感受就是,先看到只有背景色的图像,然后看到画上内容的图像,
这样就会感觉闪烁了。

解决方法:尽量快的输出图像,使输出在一个刷新周期内完成,如果输出内容很多比较慢,那么采用
内存缓冲的方法,先把要输出的内容在内存准备好,然后一次输出到显存。要知道一次API调用一般可以
在一个刷新周期内完成。

对于GDI,用创建内存DC的方法就可以了

原因二:

复杂的界面有多层窗口组成,当windows在窗口改变大小的时候是先重画父窗口,然后重画子窗口,子父
窗口重画的过程一般无法在一个刷新周期内完成,所以会呈现闪烁。

我们知道父窗口上被子窗口挡住的部分其实没必要重画的

解决方法:给窗口加个风格 WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。

如果同级窗口之间有重叠,那么需要再加上 WS_CLIPSIBLINGS 风格

原因三:

有时候需要在窗口上使用一些控件,比如IE,当你的窗口改变大小的时候IE会闪烁,即使你有了WS_CLIPCHILDREN
也没用。原因在于窗口的类风格有CS_HREDRAW 或者 CS_VREDRAW,这两个风格表示窗口在宽度或者高度变化的时候
重画,但是这样就会引起IE闪烁

解决方法:注册窗口类的时候不要使用这两个风格,如果窗口需要在改变大小的时候重画,那么可以在WM_SIZE的时候
调用RedrawWindow。

原因四:

界面上窗口很多,而且改变大小时很多窗口都要移动和改变大小,如果使用MoveWindow或者SetWindowPos两个API来
改变窗口的大小和位置,由于他们是等待窗口重画完成后才返回,所以过程很慢,这样视觉效果就可能会闪烁。

解决方法:

使用以下API来处理窗口移动,BeginDeferWindowPos, DeferWindowPos,EndDeferWindowPos
先调用 BeginDeferWindowPos 设定需要移动的窗口的个数
使用DeferWindowPos,来移动窗口,这个API并不真的造成窗口移动
EndDeferWindowPos 一次性完成所有窗口的大小和位置的改变。

有个地方要特别注意,要仔细计算清楚要移动多少个窗口,BeginDeferWindowPos设定
的个数一定要和实际的个数一致,否则在Win9x下,如果实际移动的窗口数多于调用BeginDeferWindowPos
时设定的个数,可能会造成系统崩溃。在Windows NT系列下不会有这样的问题。

posted on 2004-11-26 15:15:00 by yaodong  评论(44) 阅读(13096)

 
【第1页/共2页,25条】
首页
前页
1

Powered by: Joycode.MVC引擎 0.5.1.0