加菲猫窝

房价日涨,生活艰难
随笔 - 42, 评论 - 504, 引用 - 61

导航

关于

标签

每月存档

最新留言

广告

【第1页/共6页,101条】
首页
前页
1
2007年12月07日

《TCP/IP详解》(TCP/IP Illustrated) 很多人都在看,<卷2:实现>  里面参考的代码是 4.4bsd-lite 的 source code,这个代码也有不少人找,因为书上给的下载url早就不能用了:(

从网上下载来,给大家共享一下:

4.4BSD-lite.tar.gz  http://www.mybloop.com/go/rXjhH7

4.4BSD-lite2.tar.gz  http://www.mybloop.com/go/n272eK

顺便缅怀一下 W.Richard Stevens ,太牛了。

一个人写本书容易,难得是几本书都好得不能再好,万人景仰,这才是最难最难的啊!

把那几本书翻烂先!

posted on 2007-12-07 12:03:00 by peon  评论(0) 阅读(2142)

 
2007年12月02日

     前些天发现自己的网站无法访问,询问机房这边,说是机器最近常死机,我就把网站迁移到一个朋友的主机上, 结果没过几天机器又挂了,问朋友的机房那边说是硬件防火墙被攻击了而死掉了,详细情况不知。看来不是硬件问题,多半是被SYN FLOOD或者CC攻击了。恰好原来的机房说最近购买了新的防火墙,我又放了回去。

      既然不是硬件问题而可能是攻击,我就开始检查IIS log了,发现 IIS 里面很多Timer_ConnectionIdle和Timer_MinBytesPerSecond的错误,到网络上google了一下,常见说法是说错误是因为IIS的设置不当引起的,是因为连接超时时间设置太小,解决方法是设置连接超时为600秒,把MinFileBytesPerSec的设置从240修改到0(相当于关掉该设置)。觉得这些解决方法都有问题,假如车辆防盗警报经常响,正确的解决方法是看看有谁常来打你车子的主意,或者把车子放在更安全的地方,而绝对不是关掉警报。

      因为HTTP服务需要占用TCP连接,而TCP连接时是需要占用系统资源的,而且IIS为每个连接也需要分配相应的资源(至少一个FSM是要给的)。目前的主机能够处理上万的连接就可以说是软硬件设计都很不错了(可以参见C10K )。假如恶意人员通过一台或者多台机器发起大量的连接,而不请求内容(这样不需要消耗多少攻击机器的带宽),就可以大量消耗服务器资源而达到拒绝服务的目的。

     所以 IIS 需要关闭长时间非活动的连接,这个就是Timer_ConnectionIdle 的错误由来。

     既然盾牌改进了,当然矛也要发展一下,攻击者可以给服务器故意缓慢的发送和接收内容而消耗服务器的资源,这样可以避免服务器对于Timer_ConnectionIdle 的保护,相应的IIS的防范就是 MinFileBytesPerSec 设置,MinFileBytesPerSec 属性通过以最小的数据量保持连接,来禁止恶意的或软件工作不正常的客户端消耗资源。如果吞吐量低于 MinFileBytesPerSec 设置的值,则终止连接。LOG里面就会显示Timer_MinBytesPerSecond错误(一些Timer_MinBytesPerSecond错误是因为 windows 2003 的http.sys错误引起的,解决方式是打上最新 ServicePack : http://support.microsoft.com/kb/919797   http://support.microsoft.com/kb/919797/en-us )

      所以说这些设置都是用来保护IIS服务器的,可以一定程度上抵御一些恶意的行为消耗服务器的资源,所以我反而将IIS连接超时从原来的600秒改到了30秒,就让攻击来得更加猛烈些吧!!不过我还是很纳闷: 网站不大,所以我不可能去财消灾。无怨无仇的,谁这么无聊啊?!

 

最后发现结果挺搞笑的,欢迎看后继文章。(最近挺忙, 续集暂时不会出来。希望解决这种错误的同志:假如不是攻击的话,打上微软的补丁包就好了)

posted on 2007-12-02 12:17:00 by peon  评论(3) 阅读(6743)

 
2007年09月05日

看了蝈蝈俊.net的《理解缓存》,觉得真的是一个对于web applcation 缓存应用的好文,难得的是覆盖了冰山海面下的部分。我现在做的应用可以说和缓存打的交道也不少(不过不是web应用),也写些东西来分享给大家。

1.缓存是什么?

在我看来,缓存是通过存储中间结果,缩短访问路径来减少开销,提高性能的方法。这个概括未必最科学全面,也不够具体。我们来看看一个http 动态页面访问的例子:

访问路径是 : 数据库->应用数据集->内存对象->动态页面->HTTP服务器->用户浏览器

一个简单的访问,中间经过了多个环节,我们称这些环节为访问路径,我们来看看哪些地方可以采用缓存:

  1. HTTP服务器->用户浏览器,大家都知道浏览器都有本地缓存,浏览过的页面图片脚本等都会根据http header还有html的相关指令临时保存在本地硬盘里面,假如再次访问,访问路径就变成了"本地硬盘缓存->用户浏览器", 浏览的环节大幅度减少,性能也提高了。在这个环节,经常还使用带缓存的代理服务器来提高性能。
  2. 动态页面->HTTP服务器,这里有多种方式, 比如动态页面静态化,目前大量的大型网站使用这种方式。还有WEB服务器根据一定规则缓存整个动态页面,比如asp.net的Page Cache。这里的访问路径变成了"缓存页面->HTTP服务器->用户浏览器"
  3. 本地数据集->内存对象->动态页面。常见的就是缓存数据集还有对象,这个是ASP.NET cache里面相对浓墨重彩的部分,也是Memcached发力的侧重点, 也就不多说了。
  4. 数据库->应用数据集,不少数据库实现都有查询缓存

这里缓存都在访问路径中的环节存储了中间结果,用来减少相应的开销

2.缓存本身的开销

缓存本身也是有性能开销的,一种是将内存存储到缓存中开销,一种是将内容取出来的开销。另外,缓存往往还要付出空间上的开销。另外还要付出系统复杂度的开销,这增加了开发和维护成本。

大家也听说过IE缓存太大了或者是文件系统碎片太多以后,可能相反会拖累浏览速度,测试我倒是没有做过,但是的确是完全可能的。也就是说,缓存的开销可能会不缓存而是直接访问还要大,这就是大家不想看到的了。

3. 缓存的目的

其实前面已经说过缓存是为了减少开销,提高性能,这不就是缓存的目的吗?这倒是没错,但是也不尽然。

因为开销是一个很笼统的词,具体点有CPU开销,磁盘IO开销,网络开销,数据库访问开销等,缓存对于性能的优化,除了一些大众化的优化措施以外,还得有的放矢。

以前学习写程序,大家一定都听说过什么时间换空间,空间换时间,到底什么时候要拿空间换时间,什么时候要拿时间换空间,只能看具体应用了。前面说过缓存也有开销,其实缓存就是拿某些开销换取其他开销的下降而已。比如说动态页面静态化是一些大型网站常见的优化方法,他付出了磁盘的空间和读写开销,来换取更低的CPU消耗(不用解析动态页面)和数据库访问。有些网站每天访问量没有多少,却频繁生成和更新静态页面,同时还在服务器上做下载,本来磁盘就不堪重负,这下更加是雪上加霜,可以说是缓存优化的反面例子。或者是本来内存不大,磁盘swap很多影响性能,但是却使用大量内存做页面和对象缓存,也是反面的例子。

所以说不能盲目的进行缓存优化,一个系统,性能出现了问题,或者将来可能出现问题,性能总会有一个或者若干个瓶颈,我们要做的就是平衡或者削弱这个瓶颈,缓存是重要的手段。

所以缓存的目的是针对几个主要指标,兼顾若干个其他指标,来尽量实现低开销。

比如,数据库的CPU较高,那么一般是复杂的查询或者是存储过程导致的,在前面的各个环节进行缓存优化,比如缓存数据集和内存对象,都是好的解决方法,缓存整个页面也是个好方法,但是缓存页面要付出更多的空间开销,在某些情况下,缓存数据集或者内存对象已经够了。

假如WEB服务器的CPU较高,往往是因为动态页面处理造成的,找出开销大的处理,将处理的结果对象缓存,或者是页面静态化是不错的方法,而缓存数据库结果集往往收效不大。

4. 啥样的缓存才是好缓存?

蝈蝈俊认为是命中率最高的缓存最好。我做的领域是streaming server的磁盘IO缓存和CDN的网络边缘缓存,瓶颈就是磁盘或者网络IO,这种时候,命中率就是硬道理。

但是对于web服务器来讲,影响性能的因素很多,不同的内容访问开销相差很大,什么是好缓存,虽然命中率是极为重要的指标,但是还得要综合缓存的开销,原始的访问路径/开销和性能瓶颈来综合评价。也就是说不同的应用侧重不同,跑的硬件条件和瓶颈也不一样,很难有一个简单的指标。

比如缓存一个命中率稍低,但是原始访问开销很大的对象(比如要经过复杂查询和处理的对象) 比一个命中率较高,但是原始访问开销很小的对象要划得来。我觉得假如有一个"加权命中率"会更好,原始访问开销大的对象,要给与更高的权值,再进行命中率的计算。


假如一个缓存策略可以减少某个方面的性能开销,但是却带来了新的性能瓶颈,那么它也不是个好的缓存实现。比如磁盘IO紧张,页面更新非常频繁的情况下,静态页面缓存往往就不是一个好方法(好像没有用静态化页面做聊天室的吧:->)。

到底什么是好的缓存实现呢?前面也讲过了缓存的目的,我觉得充分利用了软硬件条件,消灭了性能瓶颈的就是好缓存。

5. 如何进行缓存优化

进行缓存优化,第一是要找到性能瓶颈,第二是找到瓶颈有关的应用部分。

性能瓶颈一般还是好找,系统有那么多性能计数器,数据库n多的调优工具,查询优化分析器。好好对照厂商的技术资料和google大法,很容易找到是CPU 内存还是IO限制了性能提高。

然后就是应用针对性能瓶颈的优化,有一个2/8定律,就是说80%的性能都消耗在20%的处理中,这20%也分为两种,一种是访问比例很高的,一种是开销贼大的,当然两个都占了,就更加没说的了。我们的任务就是集中火力提升这20%的性能,缓存往往是重要的方法。

寻找开销大的操作是个细活。我们在软件设计阶段可以预见瓶颈的部位,在出现问题的时候可以猜测出现瓶颈的部位,但是除非对行业模型,相关的架构性能还有一些性能细节非常了解(也就是说你实践过n次了),否则当初的预见和猜测都可能有较大偏差的,性能优化没有银弹,实践出真知。要多多使用工具进行分析,假如在系统里本身就有一些性能计数,可以在线或者离线提取就更好了。对于成熟的运营系统,性能统计和分析往往是其必不可少的功能。



在代码里寻找性能瓶颈太过细节,就不废话了,剩下的事情就是需要分析用户行为,根据用户对内容的访问频度实现不同的缓存策略。

6. 用户行为分析

用户行为主要有两种,一种是时间行为分布,就是一个内容的访问随时间变化的规律,不同的内容常常不同,比如新闻和音乐肯定是不一样的。
另外一种是空间分布,就是用户对于不同内容的偏好程度,大家常常说80/20规律,就是指大量的访问往往集中于少量内容,80/20只是一个定性的规律,这里一般适用的规律是zipf分布,我统计过一些系统的行为,和zipf分布的吻合度还是很好的,大家可以看看我的一篇文章:http://blog.joycode.com/peon/archive/2006/08/19/80885.aspx

大型的系统,缓存所有的内容肯定是不切实际的,缓存访问比率高的部分内容大概能达到多少缓存命中率呢?我根据zipf公式做了计算,结果可以看看下面的图:

y轴为命中率,x轴为缓存的内容占所有内容的比率,不同类型的内容有不同的a值(什么是a值, 请看http://blog.joycode.com/peon/archive/2006/08/19/80885.aspx),上面除了一条lg函数曲线外,其余的是各个a值对应的命中率曲线。可以看到a=0.95的时候,刚好符合20/80的定律。
光有理论的不够,进行实际统计永远是必须的,会议室里面的讨论永远代替不了实际的统计,log分析,性能计数器都是必要的技术。

7.关于分布式缓存

缓存会增加应用的复杂度,假如应用是分布式的而缓存不是分布式的,这个复杂度将会会平方。但是分布式缓存肯定比本机缓存效率低,所以是否选择分布式缓存实现,哪些内容使用分布式缓存哪些使用本机缓存,是第一步就得考虑的。

后记:
本文的着重点在性能,但是有些东西写的虚了点,有些想写的东西又没有写出来,算是薄积薄发献丑了:>
另外推荐一篇文章: 《从LiveJournal后台发展看大规模网站性能优化方法



posted on 2007-09-05 12:31:00 by peon  评论(10) 阅读(8650)

 
2007年07月21日

     发现很多情况下,msn传输文件比qq要慢,倒不是说msn没有快的时候,但是大部分的时候是真的比QQ慢,连我这种神经比较大条的人都注意到了,google了一下,早就有人做了解答,基本上就是说msn传输文件是使用TCP,而QQ使用UDP,剩下的事情就是论证TCP传输文件没有UDP快。大概的就是下面的几个观点:

1. TCP是可靠的,需要验证数据是否到达和是否正确,而UDP是不可靠的,少做了很多事情,所以MSN的文件传输比QQ慢。

我看了当时就想笑,UDP传输不可靠,但是应用层肯定会写代码作些和TCP的可靠传输差不多的事情。也用了QQ不少时日了,从来也没有发现传输文件有问题的,用UDP作协议也很久了,不做应用层验证重传的代码,我还真不敢写。这个理由,失败。

2. TCP建立连接需要3次握手,而UDP不需要,所以TCP慢。

3次握手这个事实倒是千真万确,还好我没有那么容易被忽悠,两个人谈话之前要握握手的确要稍微费上几秒钟,但是这个关谈话的语速啥事情?假如网络的ping值达到300ms,各位看官喜欢网络游戏的,估计都不会玩了,否则垂死的boss会高兴的发现你忽然变成了木偶可以随便殴打不还手,最后你只能骂骂电信网通然后复活几分钟后又是一条好汉。但是对于TCP,这样的ping值,3次握手一般都不需要1秒钟,把这个定为文件慢慢传的罪魁祸首,似乎太不靠谱了,这个理由还是失败。

3. TCP一旦建立链接,路由就确定了,而UDP是不确定的路由方式,谁速度快走谁的线路。

这样说就说明没有作者好好理解TCP/IP协议了,TCP的链路只是一个逻辑的,又没有建立物理链路,下面跑的还是IP包,这个包走这条路,那个包完全可能走另外的路,这点TCP和UDP没有两样。理由继续失败。

4. msn服务器在国外?

有些道理,但是我听一个美国的朋友说他也喜欢用QQ传文件的。

 

     那到底是怎么回事呢?是因为微软没有做好?(题外话,个人的确觉得MSN相比QQ的飞速进步而显得动作迟缓)QQ的Fans开始摩拳擦掌,一些不那么喜欢M$的估计就要开始丢板砖了。不管立场如何,事实还是要探寻一下,本着不求甚解,薄积薄发,浅入浅出的精神,我认为有几个可能原因:

1. 两个传文件客户端都在NAT后面的时候 (你不知道NAT啥意思?比如多个人通过路由器共享一个猫上网,那么你们一般就是在NAT后面了),从技术实现上讲,TCP在这种情况下穿越NAT比UDP麻烦得多。UDP只要开始几个穿越NAT的协商包需要服务器转一下,后面的文件数据可以两个客户端之间直接传输搞定,但是一般TCP就只能全程由服务器中转了,你说哪一个会比较快? 为什么TCP需要服务器中转?先看看NAT吧,听说有高人可以用raw sock搞定,反正我没有中间服务器搞不定。

 

2. 但是即使上面的条件不成立,msn还是一般比QQ慢的。问题还是在出在前面提到的验证数据可靠性上面,TCP是可靠的,UDP是不可靠的,但是用UDP做传输文件这档子事情,肯定要在应用层写一个验证的协议,否则传过来的文件缺胳膊少腿,会被用户骂死的。说是协议,其实也不难,打个比方吧:

    long long ago,贾宝玉在北京,林黛玉在长沙,怎么互诉衷肠呢,派家丁送信!路途遥远,怎么知道信收到没有?打电话问?那时候发明了这个就不用送信了,只能看家丁是否带了回信来了。假如发现一个家丁一个月还没有回,那就多半迷路堵车遭遇山贼或者开小差到扬州花差快活去了,再派一个人送吧! TCP就是这么做的,UDP在应用层协议一般也需要这么做,但是实现上有时候往往有区别。

    北京到长沙之间的路,并不是只有一个人跑的,常常会发生拥堵,假如发现家丁好久没有回了,TCP版的贾宝玉再派人送信是要的,但是他会比较识大体,他会少写信,降低发送速度,原来一天一封,现在可能一周一封了。他想,大家假如都这样,路就不会那么拥挤了。这做法很有道理,假如塞车了大家都想见缝插针,只能越来越塞,最后大家都动不了,还不如彼此容让慢慢排队。而UDP版本的贾宝玉假如也这么集体主义,那么他就叫做TCP友好流,就假如它只管自己拼命挤,就是非TCP友好的。

    所有的TCP协议实现假如发现拥塞,都会马上降低自己的发送速度。假如基于UDP的协议不这么做的话,原来拥塞的IP包加上重发的包,网路只会越来越拥塞,最后所有的坚持集体主义的TCP流都会做出牺牲,把带宽让给一些非TCP友好的UDP流。所以除非网络状况非常好,否则TCP是拼不过非TCP友好的协议的。

    我怀疑(仅仅是怀疑而已,我也没有条件和时间验证),QQ的文件传输机制是不那么TCP友好的,它抢带宽更加"我能",这样虽然对于整个网络负荷不是什么好事,但是对于单个用户,就见仁见智了,就好像大家看待多线程下载或者p2p一样。

posted on 2007-07-21 11:59:00 by peon  评论(30) 阅读(10930)

 
2007年05月26日

本文含有图片,无法贴上,请下载WORD文档阅读下载

有时你想这样管理某些对象,要让某种类型的对象能够自我销毁,也就是能够“delete this.” 很明显这种管理方式需要此类型对象要被分配在堆中。而其它一些时候你想获得一种保障:“不在堆中分配对象,从而保证某种类型的类不会发生内存泄漏。”如果你在嵌入式系统上工作,就有可能遇到这种情况,发生在嵌入式系统上的内存泄漏是极其严重的,其堆空间是非常珍贵的。有没有可能编写出代码来要求或禁止在堆中产生对象(heap-based object)呢?通常是可以的,不过这种代码也会把“on the heap”的概念搞得比你脑海中所想的要模糊。

要求在堆中建立对象

让我们先从必须在堆中建立对象开始说起。为了执行这种限制,你必须找到一种方法禁止以调用“new”以外的其它手段建立对象。这很容易做到。非堆对象(non-heap object)在定义它的地方被自动构造,在生存时间结束时自动被释放,所以只要禁止使用隐式的构造函数和析构函数,就可以实现这种限制。

把这些调用变得不合法的一种最直接的方法是把构造函数和析构函数声明为private。这样做副作用太大。没有理由让这两个函数都是private。最好让析构函数成为private,让构造函数成为public。处理过程与条款26相似,你可以引进一个专用的伪析构函数,用来访问真正的析构函数。客户端调用伪析构函数释放他们建立的对象。

例如,如果我们想仅仅在堆中建立代表unlimited precision numbers无限精确度数字的对象,可以这样做

class UPNumber {

public:

  UPNumber();

  UPNumber(int initValue);

  UPNumber(double initValue);

  UPNumber(const UPNumber& rhs);

 

  // 伪析构函数 (一个const 成员函数, 因为

  // 即使是const对象也能被释放。)

  void destroy() const { delete this; }

 

  ...

 

private:

  ~UPNumber();

};

然后客户端这样进行程序设计:

UPNumber n;                          // 错误! (在这里合法,但是

                                     // 当它的析构函数被隐式地

                                     // 调用时,就不合法了)

 

UPNumber *p = new UPNumber;          //正确

 

...

 

delete p;                            // 错误! 试图调用

                                     // private 析构函数

 

p->destroy();                        // 正确

另一种方法是把全部的构造函数都声明为private。这种方法的缺点是一个类经常有许多构造函数,类的作者必须记住把它们都声明为private。否则如果这些函数就会由编译器生成,构造函数包括拷贝构造函数,也包括缺省构造函数;编译器生成的函数总是public(参见Effecitve C++ 条款45)。因此仅仅声明析构函数为private是很简单的,因为每个类只有一个析构函数。

通过限制访问一个类的析构函数或它的构造函数来阻止建立非堆对象,但是在条款26已经说过,这种方法也禁止了继承和包容(containment):

class UPNumber { ... };              // 声明析构函数或构造函数

                                     // private

 

class NonNegativeUPNumber:

  public UPNumber { ... };           // 错误! 析构函数或

                                     //构造函数不能编译

 

class Asset {

private:

  UPNumber value;

  ...                                // 错误! 析构函数或

                                     //构造函数不能编译

};

这些困难不是不能克服的。通过把UPNumber的析构函数声明为protected(同时它的构造函数还保持public)就可以解决继承的问题,需要包含UPNumber对象的类可以修改为包含指向UPNumber的指针:

class UPNumber { ... };              // 声明析构函数为protected

 

class NonNegativeUPNumber:

  public UPNumber { ... };           // 现在正确了; 派生类

                                     // 能够访问

                                     // protected 成员

 

class Asset {

public:

  Asset(int initValue);

  ~Asset();

  ...

 

private:

  UPNumber *value;

};

 

Asset::Asset(int initValue)

: value(new UPNumber(initValue))      // 正确

{ ... }

 

Asset::~Asset()

{ value->destroy(); }                 // 也正确

判断一个对象是否在堆中

如果我们采取这种方法,我们必须重新审视一下“在堆中”这句话的含义。上述粗略的类定义表明一个非堆的NonNegativeUPNumber对象是合法的:

NonNegativeUPNumber n;                // 正确

那么现在NonNegativeUPNumber对象n中的UPNumber部分也不在堆中,这样说对么?答案要依据类的设计和实现的细节而定,但是让我们假设这样说是不对的,所有UPNumber对象 —即使是做为其它派生类的基类—也必须在堆中。我们如何能强制执行这种约束呢?

没有简单的办法。UPNumber的构造函数不可能判断出它是否做为堆对象的基类而被调用。也就是说对于UPNumber的构造函数来说没有办法侦测到下面两种环境的区别:

NonNegativeUPNumber *n1 =

  new NonNegativeUPNumber;            // 在堆中

 

NonNegativeUPNumber n2;               //不再堆中

不过你可能不相信我。也许你想你能够在new操作符、operator newnew 操作符调用的构造函数的相互作用中玩些小把戏(参见条款8)。可能你认为你比他们都聪明,可以这样修改UPNumber,如下所示:

class UPNumber {

public:

  // 如果建立一个非堆对象,抛出一个异常

  class HeapConstraintViolation {};

 

  static void * operator new(size_t size);

 

  UPNumber();

  ...

 

private:

  static bool onTheHeap;                 //在构造函数内,指示

                                         // 对象是否被构造在

  ...                                    // 堆上

 

};

 

// obligatory definition of class static

bool UPNumber::onTheHeap = false;

 

void *UPNumber::operator new(size_t size)

{

  onTheHeap = true;

  return ::operator new(size);

}

 

UPNumber::UPNumber()

{

  if (!onTheHeap) {

    throw HeapConstraintViolation();

  }

 

  proceed with normal construction here;

 

  onTheHeap = false;                    // 为下一个对象清除标记

}

如果不再深入研究下去,就不会发现什么错误。这种方法利用了这样一个事实:“当在堆上分配对象时,会调用operator new来分配raw memory”,operator new设置onTheHeaptrue,每个构造函数都会检测onTheHeap,看对象的raw memory是否被operator new所分配。如果没有,一个类型为HeapConstraintViolation的异常将被抛出。否则构造函数如通常那样继续运行,当构造函数结束时,onTheHeap被设置为false,然后为构造下一个对象而重置到缺省值。

这是一个非常好的方法,但是不能运行。请考虑一下这种可能的客户端代码:

UPNumber *numberArray = new UPNumber[100];

第一个问题是为数组分配内存的是operator new[],而不是operator new,不过(倘若你的编译器支持它)你能象编写operator new一样容易地编写operator new[]函数。更大的问题是numberArray100个元素,所以会调用100次构造函数。但是只有一次分配内存的调用,所以100个构造函数中只有第一次调用构造函数前把onTheHeap设置为true。当调用第二个构造函数时,会抛出一个异常,你真倒霉。

即使不用数组,bit-setting操作也会失败。考虑这条语句:

UPNumber *pn = new UPNumber(*new UPNumber);

这里我们在堆中建立两个UPNumber,让pn指向其中一个对象;这个对象用另一个对象的值进行初始化。这个代码有一个内存泄漏,我们先忽略这个泄漏,这有利于下面对这条表达式的测试,执行它时会发生什么事情:

new UPNumber(*new UPNumber)

它包含new 操作符的两次调用,因此要调用两次operator new和调用两次UPNumber构造函数(参见条款8)。程序员一般期望这些函数以如下顺序执行:

调用第一个对象的operator new

调用第一个对象的构造函数

调用第二个对象的operator new

调用第二个对象的构造函数

但是C++语言没有保证这就是它调用的顺序。一些编译器以如下这种顺序生成函数调用:

调用第一个对象的operator new

调用第二个对象的operator new

调用第一个对象的构造函数

调用第二个对象的构造函数

编译器生成这种代码丝毫没有错,但是在operator newset-a-bit的技巧无法与这种编译器一起使用。因为在第一步和第二步设置的bit,第三步中被清除,那么在第四步调用对象的构造函数时,就会认为对象不再堆中,即使它确实在。

这些困难没有否定让每个构造函数检测*this指针是否在堆中这个方法的核心思想,它们只是表明检测在operator new(operator new[])里的bit set不是一个可靠的判断方法。我们需要更好的方法进行判断。

如果你陷入了极度绝望当中,你可能会沦落进不可移植的领域里。例如你决定利用一个在很多系统上存在的事实,程序的地址空间被做为线性地址管理,程序的栈从地址空间的顶部向下扩展,堆则从底部向上扩展:

在以这种方法管理程序内存的系统里(很多系统都是,但是也有很多不是这样),你可能会想能够使用下面这个函数来判断某个特定的地址是否在堆中:

// 不正确的尝试,来判断一个地址是否在堆中

bool onHeap(const void *address)

{

  char onTheStack;                   // 局部栈变量

 

  return address < &onTheStack;

}

这个函数背后的思想很有趣。在onHeap函数中onTheSatck是一个局部变量。因此它在堆栈上。当调用onHeap时,它的栈框架(stack frame(也就是它的activation record)被放在程序栈的顶端,因为栈在结构上是向下扩展的(趋向低地址),onTheStack的地址肯定比任何栈中的变量或对象的地址小。如果参数address的地址小于onTheStack的地址,它就不会在栈上,而是肯定在堆上。

posted on 2007-05-26 09:27:00 by peon  评论(0) 阅读(660)

 

到目前为止,这种逻辑很正确,但是不够深入。最根本的问题是对象可以被分配在三个地方,而不是两个。是的,栈和堆能够容纳对象,但是我们忘了静态对象。静态对象是那些在程序运行时仅能初始化一次的对象。静态对象不仅仅包括显示地声明为static的对象,也包括在全局和命名空间里的对象(参见条款47)。这些对象肯定位于某些地方,而这些地方既不是栈也不是堆。

它们的位置是依据系统而定的,但是在很多栈和堆相向扩展的系统里,它们位于堆的底端。先前内存管理的图片到讲述的是事实,不过是很多系统都具有的事实,但是没有告诉我们这些系统全部的事实,加上静态变量后,这幅图片如下所示:

onHeap不能工作的原因立刻变得很清楚了,不能辨别堆对象与静态对象的区别:

void allocateSomeObjects()

{

  char *pc = new char;               // 堆对象: onHeap(pc)

                                     // 将返回true

 

  char c;                            // 栈对象: onHeap(&c)

                                     // 将返回false

 

  static char sc;                    // 静态对象: onHeap(&sc)

                                     // 将返回true

  ...

 

}

现在你可能不顾一切地寻找区分堆对象与栈对象的方法,在走头无路时你想在可移植性上打主意,但是你会这么孤注一掷地进行一个不能获得正确结果的交易么?绝对不会。我知道你会拒绝使用这种虽然诱人但是不可靠的“地址比对”技巧。

令人伤心的是不仅没有一种可移植的方法来判断对象是否在堆上,而且连能在多数时间正常工作的“准可移植”的方法也没有。如果你实在非得必须判断一个地址是否在堆上,你必须使用完全不可移植的方法,其实现依赖于系统调用,只能这样做了。因此你最好重新设计你的软件,以便你可以不需要判断对象是否在堆中。

如果你发现自己实在为对象是否在堆中这个问题所困扰,一个可能的原因是你想知道对象是否能在其上安全调用delete。这种删除经常采用“delete this”这种声明狼籍的形式。不过知道“是否能安全删除一个指针”与“只简单地知道一个指针是否指向堆中的事物”不一样,因为不是所有在堆中的事物都能被安全地delete。再考虑包含UPNumber对象的Asset对象:

class Asset {

private:

  UPNumber value;

  ...

 

};

 

Asset *pa = new Asset;

很明显*pa(包括它的成员value)在堆上。同样很明显在指向pa->value上调用delete是不安全的,因为该指针不是被new返回的。

幸运的是“判断是否能够删除一个指针”比“判断一个指针指向的事物是否在堆上”要容易。因为对于前者我们只需要一个operator new返回的地址集合。因为我们能自己编写operator new函数(参见Effective C++条款8—条款10),所以构建这样一个集合很容易。如下所示,我们这样解决这个问题:

void *operator new(size_t size)

{

  void *p = getMemory(size);         //调用一些函数来分配内存,

                                     //处理内存不够的情况

 

  p加入到一个被分配地址的集合;

 

  return p;

 

}

 

void operator delete(void *ptr)

{

  releaseMemory(ptr);                // return memory to

                                     // free store

 

  从被分配地址的集合中移去ptr;

}

 

bool isSafeToDelete(const void *address)

{

  返回address是否在被分配地址的集合中;

}

这很简单,operator new在地址分配集合里加入一个元素,operator delete从集合中移去项目,isSafeToDelete在集合中查找并确定某个地址是否在集合中。如果operator new operator delete函数在全局作用域中,它就能适用于所有的类型,甚至是内建类型。

在实际当中,有三种因素制约着对这种设计方式的使用。第一是我们极不愿意在全局域定义任何东西,特别是那些已经具有某种含义的函数,象operator newoperator delete正如我们所知,只有一个全局域,只有一种具有正常特征形式(也就是参数类型)的operator newoperator delete 。这样做会使得我们的软件与其它也实现全局版本的operator new 和operator delete的软件(例如许多面向对象数据库系统)不兼容。

 

我们考虑的第二个因素是效率:如果我们不需要这些,为什么还要为跟踪返回的地址而负担额外的开销呢?

最后一点可能有些平常,但是很重要。实现isSafeToDelete让它总能够正常工作是不可能的。难点是多继承下来的类或继承自虚基类的类有多个地址,所以无法保证传给isSafeToDelete的地址与operator new 返回的地址相同,即使对象在堆中建立。有关细节参见条款24和条款31

我们希望这些函数提供这些功能时能够不污染全局命名空间,没有额外的开销,没有正确性问题。幸运的是C++使用一种抽象mixin基类满足了我们的需要。

抽象基类是不能被实例化的基类,也就是至少具有一个纯虚函数的基类。mixin(mix in)类提供某一特定的功能,并可以与其继承类提供的其它功能相兼容(参见Effective C++条款7)。这种类几乎都是抽象类。因此我们能够使用抽象混合(mixin)基类给派生类提供判断指针指向的内存是否由operator new分配的能力。该类如下所示:

class HeapTracked {                  // 混合类; 跟踪

public:                              // operator new返回的ptr

 

  class MissingAddress{};            // 异常类,见下面代码

 

  virtual ~HeapTracked() = 0;

 

  static void *operator new(size_t size);

  static void operator delete(void *ptr);

 

  bool isOnHeap() const;

 

private:

  typedef const void* RawAddress;

  static list<RawAddress> addresses;

};

这个类使用了list(链表)数据结构跟踪从operator new返回的所有指针,list标准C++库的一部分(参见Effective C++条款49和本书条款35)。operator new函数分配内存并把地址加入到list中;operator delete用来释放内存并从list中移去地址元素。isOnHeap判断一个对象的地址是否在list中。

HeapTracked类的实作(我觉得把implementation翻译成“实作”更好 译者注)很简单,调用全局的operator newoperator delete函数来完成内存的分配与释放,list类里的函数进行插入操作和删除操作,并进行单语句的查找操作。以下是HeapTracked的全部实作:

// mandatory definition of static class member

list<RawAddress> HeapTracked::addresses;

 

// HeapTracked的析构函数是纯虚函数,使得该类变为抽象类。

// (参见Effective C++条款14). 然而析构函数必须被定义,

//所以我们做了一个空定义。.

HeapTracked::~HeapTracked() {}

 

 

 

void * HeapTracked::operator new(size_t size)

{

  void *memPtr = ::operator new(size);  // 获得内存

 

  addresses.push_front(memPtr);         // 把地址放到list的前端

  return memPtr;

}

 

void HeapTracked::operator delete(void *ptr)

{

  //得到一个 "iterator",用来识别list元素包含的ptr

  //有关细节参见条款35

  list<RawAddress>::iterator it =

    find(addresses.begin(), addresses.end(), ptr);

 

  if (it != addresses.end()) {       // 如果发现一个元素

    addresses.erase(it);             //则删除该元素

    ::operator delete(ptr);          // 释放内存

  } else {                           // 否则

    throw MissingAddress();          // ptr就不是用operator new

  }                                  // 分配的,所以抛出一个异常

}

 

bool HeapTracked::isOnHeap() const

{

  // 得到一个指针,指向*this占据的内存空间的起始处,

  // 有关细节参见下面的讨论

  const void *rawAddress = dynamic_cast<const void*>(this);

 

  // operator new返回的地址list中查到指针

  list<RawAddress>::iterator it =

    find(addresses.begin(), addresses.end(), rawAddress);

 

  return it != addresses.end();      // 返回it是否被找到

}

尽管你可能对list类和标准C++库的其它部分不很熟悉,代码还是很一目了然。条款35将解释这里的每件东西,不过代码里的注释已经能够解释这个例子是如何运行的。

只有一个地方可能让你感到困惑,就是这个语句(在isOnHeap函数中)

const void *rawAddress = dynamic_cast<const void*>(this);

我前面说过带有多继承或虚基类的对象会有几个地址,这导致编写全局函数isSafeToDelete会很复杂。这个问题在isOnHeap中仍然会遇到,但是因为isOnHeap仅仅用于HeapTracked对象中,我们能使用dynamic_cast操作符的一种特殊的特性来消除这个问题。只需简单地放入dynamic_cast,把一个指针dynamic_castvoid*类型(或const void*volatile void* 。。。。。),生成的指针指向“原指针指向对象内存”的开始处。但是dynamic_cast只能用于“指向至少具有一个虚拟函数的对象”的指针上。我们该死的isSafeToDelete函数可以用于指向任何类型的指针,所以dynamic_cast也不能帮助它。isOnHeap更具有选择性(它只能测试指向HeapTracked对象的指针),所以能把this指针dynamic_castconst void*,变成一个指向当前对象起始地址的指针。如果HeapTracked::operator new为当前对象分配内存,这个指针就是HeapTracked::operator new返回的指针。如果你的编译器支持dynamic_cast 操作符,这个技巧是完全可移植的。

使用这个类,即使是最初级的程序员也可以在类中加入跟踪堆中指针的功能。他们所需要做的就是让他们的类从HeapTracked继承下来。例如我们想判断Assert对象指针指向的是否是堆对象:

class Asset: public HeapTracked {

private:

  UPNumber value;

  ...

};

我们能够这样查询Assert*指针,如下所示:

void inventoryAsset(const Asset *ap)

{

  if (ap->isOnHeap()) {

    ap is a heap-based asset — inventory it as such;

  }

  else {

    ap is a non-heap-based asset — record it that way;

  }

}

HeapTracked这样的混合类有一个缺点,它不能用于内建类型,因为象intchar这样的类型不能继承自其它类型。不过使用象HeapTracked的原因一般都是要判断是否可以调用”delete this”,你不可能在内建类型上调用它,因为内建类型没有this指针。

禁止堆对象

判断对象是否在堆中的测试到现在就结束了。与此相反的领域是“禁止在堆中建立对象”。通常对象的建立这样三种情况:对象被直接实例化;对象做为派生类的基类被实例化;对象被嵌入到其它对象内。我们将按顺序地讨论它们。

禁止客户端直接实例化对象很简单,因为总是调用new来建立这种对象,你能够禁止客户端调用new。你不能影响new操作符的可用性(这是内嵌于语言的),但是你能够利用new操作符总是调用operator new函数这点(参见条款8),来达到目的。你可以自己声明这个函数,而且你可以把它声明为private.。例如,如果你想不想让客户端在堆中建立UPNumber对象,你可以这样编写:

class UPNumber {

private:

  static void *operator new(size_t size);

  static void operator delete(void *ptr);

  ...

};

现在客户端仅仅可以做允许它们做的事情:

UPNumber n1;                         // okay

 

static UPNumber n2;                  // also okay

 

UPNumber *p = new UPNumber;          // error! attempt to call

                                     // private operator new

operator new声明为private就足够了,但是把operator new声明为private,而把iperator delete声明为public,这样做有些怪异,所以除非有绝对需要的原因,否则不要把它们分开声明,最好在类的一个部分里声明它们。如果你也想禁止UPNumber堆对象数组,可以把operator new[]operator delete[](参见条款8)也声明为private。(operator newoperator delete之间的联系比大多数人所想象的要强得多。有关它们之间关系的鲜为人知的一面,可以参见我的文章counting objects里的sidebar部分。)

有趣的是,把operator new声明为private经常会阻碍UPNumber对象做为一个位于堆中的派生类对象的基类被实例化。因为如果operator newoperator delete没有在派生类中被声明为public,它们就会被继承下来,继承了基类private函数的类,如下所示:

class UPNumber { ... };             // 同上

 

class NonNegativeUPNumber:          //假设这个类

  public UPNumber {                 //没有声明operator new

  ...

};

 

NonNegativeUPNumber n1;             // 正确

 

static NonNegativeUPNumber n2;      // 也正确

 

NonNegativeUPNumber *p =            // 错误! 试图调用

  new NonNegativeUPNumber;          // private operator new

如果派生类声明它自己的operator new,当在堆中分配派生对象时,就会调用这个函数,必须得找到一种不同的方法防止UPNumber基类部分缠绕在这里。同样,UPNumberoperator newprivate这一点,不会对分配包含做为成员的UPNumber对象的对象产生任何影响:

class Asset {

public:

  Asset(int initValue);

  ...

 

private:

  UPNumber value;

};

 

Asset *pa = new Asset(100);          // 正确, 调用

                                     // Asset::operator new

                                     // ::operator new, 不是

                                     // UPNumber::operator new

实际上,我们又回到了这个问题上来,即“如果UPNumber对象没有被构造在堆中,我们想抛出一个异常”。当然这次的问题是“如果对象在堆中,我们想抛出异常”。正像没有可移植的方法来判断地址是否在堆中一样,也没有可移植的方法判断地址是否不在堆中,所以我们很不走运,不过这也丝毫不奇怪,毕竟如果我们能辨别出某个地址在堆上,我们也就能辨别出某个地址不在堆上。但是我们什么都不能辨别出来。

posted on 2007-05-26 09:26:00 by peon  评论(0) 阅读(719)

 

灵巧指针是一种外观和行为都被设计成与内建指针相类似的对象,不过它能提供更多的功能。它们有许多应用的领域,包括资源管理(参见条款9、10、25和31)和重复代码任务的自动化(参见条款17和29)

当你使用灵巧指针替代C++的内建指针(也就是dumb pointer),你就能控制下面这些方面的指针的行为:

构造和析构。你可以决定建立灵巧指针时应该怎么做。通常赋给灵巧指针缺省值0,避免出现令人头疼的未初始化的指针。当指向某一对象的最后一个灵巧指针被释放时,一些灵巧指针负责删除它们指向的对象。这样做对防止资源泄漏很有帮助。

拷贝和赋值。你能对拷贝灵巧指针或设计灵巧指针的赋值操作进行控制。对于一些类型的灵巧指针来说,期望的行为是自动拷贝它们所指向的对象或用对这些对象进行赋值操作,也就是进行deep copy(深层拷贝)。对于其它的一些灵巧指针来说,仅仅拷贝指针本身或对指针进行赋值操作。还有一部分类型的灵巧指针根本就不允许这些操作。无论你认为应该如何去做,灵巧指针始终受你的控制。

Dereferencing(取出指针所指东西的内容)。当客户端引用被灵巧指针所指的对象,会发生什么事情呢?你可以自行决定。例如你可以用灵巧指针实现条款17提到的lazy fetching 方法。

灵巧指针从模板中生成,因为要与内建指针类似,必须是strongly typed(强类型)的;模板参数确定指向对象的类型。大多数灵巧指针模板看起来都象这样:

template<class T>                    //灵巧指针对象模板

class SmartPtr {                    

public:

  SmartPtr(T* realPtr = 0);          // 建立一个灵巧指针

                                     // 指向dumb pointer所指的

                                     // 对象。未初始化的指针

                                     // 缺省值为0(null)

 

  SmartPtr(const SmartPtr& rhs);     // 拷贝一个灵巧指针

 

  ~SmartPtr();                       // 释放灵巧指针

 

  // make an assignment to a smart ptr

  SmartPtr& operator=(const SmartPtr& rhs);

 

  T* operator->() const;             // dereference一个灵巧指针

                                     // 以访问所指对象的成员

 

  T& operator*() const;              // dereference 灵巧指针

 

private:

  T *pointee;                        // 灵巧指针所指的对象

};                                 

拷贝构造函数和赋值操作符都被展现在这里。对于灵巧指针类来说,不能允许进行拷贝和赋值操作,它们应该被声明为private(参见Effective C++条款27)。两个dereference操作符被声明为const,是因为dereference一个指针时不能对指针进行修改(尽管可以修改指针所指的对象)。最后,每个指向T对象的灵巧指针包含一个指向T的dumb pointer。这个dumb pointer指向的对象才是灵巧指针指向的真正对象。

进入灵巧指针实作的细节之前,应该研究一下客户端如何使用灵巧指针。考虑一下,存在一个分布式系统(即其上的对象一些在本地,一些在远程)。相对于访问远程对象,访问本地对象通常总是又简单而且速度又快,因为远程访问需要远程过程调用(RPC),或其它一些联系远距离计算机的方法。

对于编写程序代码的客户端来说,采用不同的方法分别处理本地对象与远程对象是一件很烦人的事情。让所有的对象都位于一个地方会更方便。灵巧指针可以让程序库实现这样的梦想。

template<class T>                    // 指向位于分布式 DB(数据库)

class DBPtr {                        // 中对象的灵巧指针模板

public:                              //

 

  DBPtr(T *realPtr = 0);             // 建立灵巧指针,指向

                                     // 由一个本地dumb pointer

                                     // 给出的DB 对象

 

 

  DBPtr(DataBaseID id);              // 建立灵巧指针,

                                     // 指向一个DB对象,

                                     // 具有惟一的DB识别符

 

  ...                                // 其它灵巧指针函数

};                                   //同上

 

class Tuple {                        // 数据库元组类

public:                            

  ...

  void displayEditDialog();          // 显示一个图形对话框,

                                     // 允许用户编辑元组。

                                     // user to edit the tuple

 

  bool isValid() const;              // 返回*this是否通过了

};                                   // 合法性验证

 

// 这个类模板用于在修改T对象时进行日志登记。

// 有关细节参见下面的叙述:

template<class T>

class LogEntry {

public:

  LogEntry(const T& objectToBeModified);

  ~LogEntry();

};

 

void editTuple(DBPtr<Tuple>& pt)

{

  LogEntry<Tuple> entry(*pt);        // 为这个编辑操作登记日志

                                     // 有关细节参见下面的叙述

 

  // 重复显示编辑对话框,直到提供了合法的数值。

  do {

    pt->displayEditDialog();

  } while (pt->isValid() == false);

}

editTuple中被编辑的元组物理上可以位于本地也可以位于远程,但是编写editTuple的程序员不用关心这些事情。灵巧指针类隐藏了系统的这些方面。程序员只需关心通过对象进行访问的元组,而不用关心如何声明它们,其行为就像一个内建指针。

注意在editTuple中LogEntry对象的用法。一种更传统的设计是在调用displayEditDialog前开始日志记录,调用后结束日志记录。在这里使用的方法是让LogEntry的构造函数启动日志记录,析构函数结束日志记录。正如条款9所解释的,当面对异常时,让对象自己开始和结束日志记录比显示地调用函数可以使的程序更健壮。而且建立一个LogEntry对象比每次都调用开始记录和结束记录函数更容易。

正如你所看到的,使用灵巧指针与使用dump pointer没有很大的差别。这表明了封装是非常有效的。灵巧指针的客户端可以象使用dumb pointer一样使用灵巧指针。正如我们将看到的,有时这种替代会更透明化。

灵巧指针的构造、赋值和析构

灵巧指针的的析构通常很简单:找到指向的对象(一般由灵巧指针构造函数的参数给出),让灵巧指针的内部成员dumb pointer指向它。如果没有找到对象,把内部指针设为0或发出一个错误信号(可以是抛出一个异常)。

灵巧指针拷贝构造函数、赋值操作符函数和析构函数的实作由于所有权的问题所以有些复杂。如果一个灵巧指针拥有它指向的对象,当它被释放时必须负责删除这个对象。这里假设灵巧指针指向的的对象是动态分配的。这种假设在灵巧指针中是常见的(有关确定这种假设是真实的方法,参见条款27)。

看一下标准C++类库中auto_ptr模板。这如条款9所解释的,一个auto_ptr对象是一个指向堆对象的灵巧指针,直到auto_ptr被释放。auto_ptr的析构函数删除其指向的对象时,会发生什么事情呢?auto_ptr模板的实作如下:

template<class T>

class auto_ptr {

public:

  auto_ptr(T *ptr = 0): pointee(ptr) {}

  ~auto_ptr() { delete pointee; }

  ...

 

private:

  T *pointee;

};

假如auto_ptr拥有对象时,它可以正常运行。但是当auto_ptr被拷贝或被赋值时,会发生什么情况呢?

auto_ptr<TreeNode> ptn1(new TreeNode);

 

auto_ptr<TreeNode> ptn2 = ptn1;      // 调用拷贝构造函数

                                     //会发生什么情况?

 

auto_ptr<TreeNode> ptn3;

 

ptn3 = ptn2;                         // 调用 operator=;

                                     // 会发生什么情况?

如果我们只拷贝内部的dumb pointer,会导致两个auto_ptr指向一个相同的对象。这是一个灾难,因为当释放quto_ptr时每个auto_ptr都会删除它们所指的对象。这意味着一个对象会被我们删除两次。这种两次删除的结果将是不可预测的(通常是灾难性的)。

另一种方法是通过调用new,建立一个所指对象的新拷贝。这确保了不会有许多指向同一个对象的auto_ptr,但是建立(以后还得释放)新对象会造成不可接受的性能损耗。并且我们不知道要建立什么类型的对象,因为auto_ptr<T>对象不用必须指向类型为T的对象,它也可以指向T的派生类型对象。虚拟构造函数(参见条款25)可能帮助我们解决这个问题,但是好象不能把它们用在auto_ptr这样的通用类中。

如果quto_ptr禁止拷贝和赋值,就可以消除这个问题,但是采用“当auto_ptr被拷贝和赋值时,对象所有权随之被传递”的方法,是一个更具灵活性的解决方案:

template<class T>

class auto_ptr {

public:

  ...

 

  auto_ptr(auto_ptr<T>& rhs);        // 拷贝构造函数

 

  auto_ptr<T>&                       // 赋值

  operator=(auto_ptr<T>& rhs);       // 操作符

 

  ...

};

 

template<class T>

auto_ptr<T>::auto_ptr(auto_ptr<T>& rhs)

{

  pointee = rhs.pointee;             // *pointee的所有权

                                     // 传递到 *this

 

  rhs.pointee = 0;                   // rhs不再拥有

}                                    // 任何东西

 

template<class T>

auto_ptr<T>& auto_ptr<T>::operator=(auto_ptr<T>& rhs)

{

  if (this == &rhs)                  // 如果这个对象自我赋值

    return *this;                    // 什么也不要做

                                   

 

  delete pointee;                    // 删除现在拥有的对象

                                  

 

  pointee = rhs.pointee;             // *pointee的所有权

  rhs.pointee = 0;                   // rhs 传递到 *this

 

  return *this;

}

注意赋值操作符在接受新对象的所有权以前必须删除原来拥有的对象。如果不这样做,原来拥有的对象将永远不会被删除。记住,除了auto_ptr对象,没有人拥有auto_ptr指向的对象。

因为当调用auto_ptr的拷贝构造函数时,对象的所有权被传递出去,所以通过传值方式传递auto_ptr对象是一个很糟糕的方法。因为:

// 这个函数通常会导致灾难发生

void printTreeNode(ostream& s, auto_ptr<TreeNode> p)

{ s << *p; }

 

int main()

{

  auto_ptr<TreeNode> ptn(new TreeNode);

 

  ...

 

  printTreeNode(cout, ptn);          //通过传值方式传递auto_ptr

 

  ...

 

}

printTreeNode的参数p被初始化时(调用auto_ptr的拷贝构造函数),ptn指向对象的所有权被传递到给了p。当printTreeNode结束执行后,p离开了作用域,它的析构函数删除它指向的对象(就是原来ptr指向的对象)。然而ptr不再指向任何对象(它的dumb pointernull),所以调用printTreeNode以后任何试图使用它的操作都将产生不可定义的行为。只有在你确实想把对象的所有权传递给一个临时的函数参数时,才能通过传值方式传递auto_ptr。这种情况很少见。

这不是说你不能把auto_ptr做为参数传递,这只意味着不能使用传值的方法。通过const引用传递(Pass-by-reference-to-const)的方法是这样的:

// 这个函数的行为更直观一些

void printTreeNode(ostream& s,

                   const auto_ptr<TreeNode>& p)

{ s << *p; }

在函数里,p是一个引用,而不是一个对象,所以不会调用拷贝构造函数初始化p。当ptn被传递到上面这个printTreeNode时,它还保留着所指对象的所有权,调用printTreeNode以后还可以安全地使用ptn。从而通过const引用传递auto_ptr可以避免传值所产生的风险。(“引用传递”替代“传值”的其他原因参见Effective C++条款22)。

在拷贝和赋值中,把对象的所有权从一个灵巧指针传递到另一个中去,这种思想很有趣,而且你可能已经注意到拷贝构造函数和赋值操作符不同寻常的声明方法同样也很有趣。这些函数同上会带有const参数,但是上面这些函数则没有。实际上在拷贝和赋值中上述这些代码修改了这些参数。也就是说,如果auto_ptr对象被拷贝或做为赋值操作的数据源,就会修改auto_ptr对象!

是的,就是这样。C++是如此灵活能让你这样去做,真是太好了。如果语言要求拷贝构造函数和赋值操作符必须带有const参数,你必须去掉参数的const属性(参见Effective C++条款21)或用其他方法实现所有权的转移。准确地说:当拷贝一个对象或这个对象做为赋值的数据源,就会修改该对象。这可能有些不直观,但是它是简单的,直接的,在这种情况下也是准确的。

如果你发现研究这些auto_ptr成员函数很有趣,你可能希望看看完整的实作。在291页至294页上有(只原书页码),在那里你也能看到在标准C++库中auto_ptr模板有比这里所描述的更灵活的拷贝构造函数和赋值操作符。在标准C++库中,这些函数是成员函数模板,不只是成员函数。(在本条款的后面会讲述成员函数模板。也可以阅读Effective C++条款25)。

灵巧指针的析构函数通常是这样的:

template<class T>

SmartPtr<T>::~SmartPtr()

{

  if (*this owns *pointee) {

    delete pointee;

  }

}

有时删除前不需要进行测试,例如在一个auto_ptr总是拥有它指向的对象时。而在另一些时候,测试会更为复杂。一个使用了引用计数(参见条款29)灵巧指针必须在判断是否有权删除所指对象前调整引用计数值。当然还有一些灵巧指针象dumb pointer一样,当它们被删除时,对所指对象没有任何影响。

实作Dereference 操作符

让我们把注意力转向灵巧指针的核心部分,the operator*  operator-> 函数。前者返回所指的对象。理论上,这很简单:
template<class T>
T& SmartPtr<T>::operator*() const
{
  perform "smart pointer" processing;
 
  return *pointee;
}

首先无论函数做什么,必须先初始化指针或使pointee合法。例如,如果使用lazy fetch(参见条款17),函数必须为pointee建立一个新对象。一旦pointee合法了,operator*函数就返回其所指对象的一个引用。

注意返回类型是一个引用。如果返回对象,尽管编译器允许这么做,这也将会导致灾难性后果。必须时刻牢记:pointee不用必须指向T类型对象;它也可以指向T的派生类对象。如果在这种情况下operator*函数返回的是T类型对象而不是派生类对象的引用,你的函数实际上返回的是一个错误类型的对象!(这是一个slicing问题,参见Effective C++条款22和本书条款13)。在返回的这种对象上调用虚拟函数,不会触发与所指对象的动态类型相符的函数。实际上就是说你的灵巧指针不能支持虚拟函数,象这样的指针再灵巧也没有用。而返回一个引用还能够具有更高的效率(不需要构造一个临时对象,参见条款19)。能够兼顾正确与效率当然是一件好事。

如果你是一个急性子的人,你可能会想如果一些人在null灵巧指针上调用operator*,也就是说灵巧指针的dumb pointernull。放松。随便做什么都行。dereference一个空指针的结果是未定义的,所以这不是一个“错误”的行为。想排除一个异常么?可以,抛出吧。想调用abort函数(可能被assert在失败时调用)?好的,调用吧。想遍历内存把每个字节都设成你生日与256模数么?当然也可以。虽说这样做没有什么好处,但是就语言本身而言,你完全是自由的。

operator->的情况与operator*是相同的,但是在分析operator->之前,让我们先回忆一下这个函数调用的与众不同的含义。再考虑editTuple函数,其使用一个指向Tuple对象的灵巧指针:

void editTuple(DBPtr<Tuple>& pt)
{
  LogEntry<Tuple> entry(*pt);
 
  do {
    pt->displayEditDialog();
  } while (pt->isValid() == false);
}

语句

pt->displayEditDialog();

被编译器解释为:
(pt.operator->())->displayEditDialog();

这意味着不论operator->返回什么,它必须使用member-selection operator(成员选择操作符)->)。因此operator->仅能返回两种东西:一个指向某对象的dumb pointer或另一个灵巧指针。多数情况下,你想返回一个普通dumb pointer。在此情况下,你这样实作operator->

template<class T>
T* SmartPtr<T>::operator->() const
{
  perform "smart pointer" processing;
 
  return pointee;
}

这样做运行良好。因为该函数返回一个指针,通过operator->调用虚拟函数,其行为也是正确的。

对于很多程序来说,这就是你需要了解灵巧指针的全部东西。条款29的引用计数代码并没有比这里更多的功能。但是如果你想更深入地了解灵巧指针,你必须知道更多的有关dumb pointer的知识和灵巧指针如何能或不能进行模拟。如果你的座右铭是“Most people stop at the Z-but not me(多数人浅尝而止,但我不能够这样) ”,下面讲述的内容正适合你。

posted on 2007-05-26 09:24:00 by peon  评论(0) 阅读(766)

 

 测试灵巧指针是否为NULL

目前为止我们讨论的函数能让我们建立、释放、拷贝、赋值、dereference灵巧指针。但是有一件我们做不到的事情是“发现灵巧指针为NULL”:

SmartPtr<TreeNode> ptn;

 

...

 

if (ptn == 0) ...                    // error!

 

if (ptn) ...                         // error!

 

if (!ptn) ...                        // error!

这是一个严重的限制。

在灵巧指针类里加入一个isNull成员函数是一件很容易的事,但是仍然没有解决当测试NULL时灵巧指针的行为与dumb pointer不相似的问题。另一种方法是提供隐式类型转换操作符,允许编译上述的测试。一般应用于这种目的的类型转换是void*

template<class T>

class SmartPtr {

public:

  ...

  operator void*();                  // 如果灵巧指针为null

  ...                                // 返回0,否则返回

};                                   // 0

 

SmartPtr<TreeNode> ptn;

 

...

 

if (ptn == 0) ...                    // 现在正确

 

if (ptn) ...                         // 也正确

 

if (!ptn) ...                        // 正确

这与iostream类中提供的类型转换相同,所以可以这样编写代码:

ifstream inputFile("datafile.dat");

 

if (inputFile) ...                   // 测试inputFile是否已经被

                                     // 成功地打开。

象所有的类型转换函数一样,它有一个缺点,在一些情况下虽然大多数程序员希望它调用失败,但是函数还能够成功地被调用(参见条款5)。特别是它允许灵巧指针与完全不同的类型之间进行比较:

SmartPtr<Apple> pa;

SmartPtr<Orange> po;

 

...

 

if (pa == po) ...                    // 这能够被成功编译!

即使在SmartPtr<Apple> SmartPtr<Orange>之间没有operator= 函数也能够编译因为灵巧指针被隐式地转换为void*指针对于内建指针类型有一个内建的比较函数。这种进行隐式类型转换的行为特性很危险。(再看一下条款5,必须反反复复地阅读,做到耳熟能详。)

void*类型转换方面,也有一些变通之策。有些设计者采用到const void*的类型转换,还有一些采取转换到bool的方法。这些变通之策都没有消除混合类型比较的问题。

有一种两全之策可以提供合理的测试空值的语法形式,同时把不同类型的灵巧指针之间进行比较的可能性降到最低。这就是在灵巧指针类中重载operator!,当且仅当灵巧指针是一个空指针时,operator!返回true:

template<class T>

class SmartPtr {

public:

  ...

  bool operator!() const;            // 当且仅当灵巧指针是

  ...                                // 空值,返回true

 

};

客户端程序如下所示

SmartPtr<TreeNode> ptn;

 

...

 

if (!ptn) {                          // 正确

  ...                                // ptn 是空值

}

else {

  ...                                // ptn不是空值

}

但是这样就不正确了:

if (ptn == 0) ...                    // 仍然错误

 

if (ptn) ...                         // 也是错误的

 

仅在这种情况下会存在不同类型之间进行比较:

SmartPtr<Apple> pa;

SmartPtr<Orange> po;

 

...

 

if (!pa == !po) ...                 // 能够编译

幸好程序员不会经常这样编写代码。有趣的是,iostream库的实作除了提供void*隐式的类型转换,也有operator!函数,不过这两个函数被用于测试的流状态有些不同。(在C++类库标准中(参见Effective C++ 条款49和本书条款35),void*隐式的类型转换已经被bool类型的转换所替代,operator bool总是返回与operator!相反的值。)

把灵巧指针转变成dumb指针

有时你要在一个程序里或已经使用dumb指针的程序库中添加灵巧指针。例如,你的分布式数据库系统原来不是分布式的,所以可能有一些老式的库函数没有使用灵巧指针:

class Tuple { ... };                 // 同上

 

void normalize(Tuple *pt);           // *pt 放入

                                     // 范式中; 注意使用的

                                     // dumb指针

考虑一下,如果你试图用指向Tuple的灵巧指针调用normalize,会出现什么情况:

DBPtr<Tuple> pt;

 

...

 

normalize(pt);                       // 错误!

 

这种调用不能够编译,因为不能把DBPtr<Tuple>转换成Tuple*。你可以这样做,从而使该该函数正常运行:

normalize(&*pt);                     // 繁琐, 但合法

不过我觉得你会讨厌这种调用方式。

在灵巧指针模板中增加指向Tdumb指针的隐式类型转换操作符,可以让以上函数调用成功运行:

template<class T>                   // 同上

class DBPtr {

public:

  ...

  operator T*() { return pointee; }

  ...

};

 

DBPtr<Tuple> pt;

 

...

 

normalize(pt);                       // 能够运行

 

并且这个函数也消除了测试空值的问题:

if (pt == 0) ...                     // 正确, pt转变成

                                     // Tuple*

 

if (pt) ...                          // 同上

 

if (!pt) ...                         // 同上 (reprise)

然而,它也有类型转换函数所具有的缺点(几乎总是这样,看条款5)。它使得客户端能够很容易地直接访问dumb指针,绕过“类指针(pointer-like)”对象所提供的“灵巧”特性:

void processTuple(DBPtr<Tuple>& pt)

{

  Tuple *rawTuplePtr = pt;           // DBPtr<Tuple> 转变成

                                     // Tuple*

 

  使用raw TuplePtr 修改 tuple;

 

}

通常,灵巧指针提供的“灵巧”行为特性是设计中的主要组成部分,所以允许客户端使用dumb指针会导致灾难性的后果。例如,如果DBPtr实现了条款29中引用计数的功能,允许客户端直接对dumb指针进行操作很可能破坏“引用计数”数据结构,而导致引用计数错误。

甚至即使你提供一个从灵巧指针到dumb指针的隐式转换操作符,灵巧指针也不能真正地做到与dumb指针互换。因为从灵巧指针到dumb指针的转换是“用户定义类型转换”,在同一时间编译器进行这种转换的次数不能超过一次。例如假设有一个表示能够访问某一元组的所有客户的类:

class TupleAccessors {

public:

  TupleAccessors(const Tuple *pt);   // pt identifies the

  ...                                // tuple whose accessors

};                                   // we care about

通常,TupleAccessors的单参数构造函数也可以做为从Tuple*TupleAccessors的类型转换操作符(参见条款5)。现在考虑一下用于合并两个TupleAccessors对象内信息的函数:

TupleAccessors merge(const TupleAccessors& ta1,

                     const TupleAccessors& ta2);

因为一个Tuple*可以被隐式地转换为TupleAccessors,用两个dumb Tuple*调用merge函数,可以正常运行:

Tuple *pt1, *pt2;

 

...

 

merge(pt1, pt2);                     // 正确, 两个指针被转换为

                                     // TupleAccessors objects

如果用灵巧指针DBPtr<Tuple>进行调用,编译就会失败:

DBPtr<Tuple> pt1, pt2;

 

...

 

merge(pt1, pt2);                 // 错误!不能把 pt1

                                 // pt2转换称TupleAccessors对象

因为从DBPtr<Tuple>TupleAccessors的转换要调用两次用户定义类型转换(一次从DBPtr<Tuple>Tuple*,一次从Tuple*TupleAccessors),编译器不会进行这种转换序列。

提供到dumb指针的隐式类型转换的灵巧指针类也暴露了一个非常有害的bug。考虑这个代码:

DBPtr<Tuple> pt = new Tuple;

 

...

 

delete pt;

这段代码应该不能被编译,pt不是指针,它是一个对象,你不能删除一个对象。只有指针才能被删除,对么?

当然对了。但是回想一下条款5:编译器使用隐式类型转换来尽可能使函数调用成功,再回想一下条款8:使用delete会调用析构函数和operator delete,两者都是函数。编译器欲使在delete语句里的两个函数成功调用,就把pt隐式转换为Tuple*,然后删除它。这样做必然会破坏你的程序。

如果pt拥有它指向的对象,对象就会被删除两次,一次在调用delete时,第二次在pt的析构函数被调用时。如果pt不拥有对象,而是其他人拥有,拥有者可以删除pt,但是如果pt指向对象的拥有者不是删除pt的人,有删除权的拥有者以后还会再次删除该对象。不论是前者所述的情况还是后者的情况都会导致一个对象被删除两次,这样做会产生不能预料的后果。

这个bug极为有害,因为隐藏在灵巧指针后面的全部思想就是让它们不论是在外观上还是在使用感觉上都与dumb指针尽可能地相似。你越接近这种思想,你的客户端就越可能忘记正在使用灵巧指针。如果他们忘记了正在使用灵巧指针,肯定会在调用new之后调用delete,以防止资源泄漏,谁又能责备他们这样做不对呢?

底线很简单:除非有一个让人非常信服的原因去这样做,否则绝对不要提供转换到dumb指针的隐式类型转换操作符。

灵巧指针和继承类到基类的类型转换

假设我们有一个public继承层次结构,以模型化音乐商店的商品:

class MusicProduct {

public:

  MusicProduct(const string& title);

  virtual void play() const = 0;

  virtual void displayTitle() const = 0;

  ...

};

 

class Cassette: public MusicProduct {

public:

  Cassette(const string& title);

  virtual void play() const;

  virtual void displayTitle() const;

  ...

};

 

class CD: public MusicProduct {

public:

  CD(const string& title);

  virtual void play() const;

  virtual void displayTitle() const;

  ...

};

 

再接着假设,我们有一个函数,给它一个MusicProduct对象,它能显示产品名,并播放它:

void displayAndPlay(const MusicProduct* pmp, int numTimes)

{

  for (int i = 1; i <= numTimes; ++i) {

    pmp->displayTitle();

    pmp->play();

  }

}

这个函数能够这样使用:

Cassette *funMusic = new Cassette("Alapalooza");

CD *nightmareMusic = new CD("Disco Hits of the 70s");

 

displayAndPlay(funMusic, 10);

displayAndPlay(nightmareMusic, 0);

这并没有什么值得惊讶的东西,但是当我们用灵巧指针替代dumb指针,会发生什么呢:

void displayAndPlay(const SmartPtr<MusicProduct>& pmp,

                    int numTimes);

 

SmartPtr<Cassette> funMusic(new Cassette("Alapalooza"));

SmartPtr<CD> nightmareMusic(new CD("Disco Hits of the 70s"));

 

displayAndPlay(funMusic, 10);         // 错误!

displayAndPlay(nightmareMusic, 0);    // 错误!

如果灵巧指针这么聪明,为什么不能编译这些代码呢?

不能进行编译原因是不能把SmartPtr<CD>SmartPtr<Cassette>转换成SmartPtr<MusicProduct>。从编译器的观点来看,这些类之间没有任何关系。为什么编译器的会这样认为呢?毕竟SmartPtr<CD> SmartPtr<Cassette>不是从SmartPtr<MusicProduct>继承过来的,这些类之间没有继承关系,我们不可能要求编译器把一种对象转换成另一种类型的对象。

幸运的是,有办法避开这种限制,这种方法的核心思想(不是实际操作)很简单:对于可以进行隐式转换的每个灵巧指针类都提供一个隐式类型转换操作符(参见条款5)。例如在music类层次内,在CassetteCD的灵巧指针类内你可以加入SmartPtr<MusicProduct>函数:

class SmartPtr<Cassette> {

public:

  operator SmartPtr<MusicProduct>()

  { return SmartPtr<MusicProduct>(pointee); }

 

  ...

 

private:

  Cassette *pointee;

};

 

class SmartPtr<CD> {

public:

  operator SmartPtr<MusicProduct>()

  { return SmartPtr<MusicProduct>(pointee); }

 

  ...

 

private:

  CD *pointee;

};

这种方法有两个缺点。第一,你必须人为地特化(specializeSmartPtr类,所以你加入隐式类型转换操作符也就破坏了模板的通用性。第二,你可能必须添加许多类型转换符,因为你指向的对象可以位于继承层次中很深的位置,你必须为直接或间接继承的每一个基类提供一个类型转换符。(如果你想你能够克服这个缺点,方法是仅仅为转换到直接基类而提供一个隐式类型转换符,那么你再想想这样做行么?因为编译器在同一时间调用用户定义类型转换函数的次数不能超过一次,它们不能把指向T的灵巧指针转换为指向T的间接基类的灵巧指针,除非只要一步就能完成。)

如果你能让编译器为你编写所有的类型转换函数,这会节省很多时间。感谢最近的语言扩展,让你能够做到,这个扩展能声明(非虚)成员函数模板(通常就叫成员模板(member template)),你能使用它来生成灵巧指针类型转换函数,如下:

template<class T>                    // 模板类,指向T

class SmartPtr {                     // 灵巧指针

public:

  SmartPtr(T* realPtr = 0);

 

  T* operator->() const;

  T& operator*() const;

 

  template<class newType>             // 模板成员函数

  operator SmartPtr<newType>()        // 为了实现隐式类型转换.

  {

    return SmartPtr<newType>(pointee);

  }

 

  ...

};

现在请你注意,这可不是魔术——不过也很接近于魔术。它的原理如下所示。(如果下面的内容让你感到既冗长又令你费解,请不要失望,一会儿我会给出一个例子。我保证你看完例子后,就能够更深入地理解这段内容了)假设编译器有一个指向T对象的灵巧指针,它要把这个对象转换成指向“T的基类”的灵巧指针。编译器首先检查SmartPtr<T>的类定义,看其有没有声明必须的类型转换符,但是它没有声明。(这不是指:在模板上面没有声明类型转换符)编译器然后检查是否存在一个成员函数模板,可以被实例化,用来进行它所期望的类型转换。它发现了一个这样的模板(带有形式类型参数newType),所以它把newType绑定到T的基类类型上,来实例化模板。这时,惟一一个问题是实例化的成员函数代码能否被编译。传递(dumb)指针pointee到指向“T的基类”的灵巧指针的构造函数,这个语句是合法的,把它转变成指向其基类(public 或 protected)对象的指针也必然是合法的,因此类型转换操作符能够被编译,可以成功地把指向T的灵巧指针隐式地类型转换为指向“T的基类”的灵巧指针。

举一个例子会有所帮助。让我们回到CDs、cassettes、music产品的继承层次上来。我们先前已经知道下面这段代码不能被编译,因为编译器不能把指向CD的灵巧指针转换为指向music产品的灵巧指针:

void displayAndPlay(const SmartPtr<MusicProduct>& pmp,

                    int howMany);

 

SmartPtr<Cassette> funMusic(new Cassette("Alapalooza"));

SmartPtr<CD> nightmareMusic(new CD("Disco Hits of the 70s"));

 

displayAndPlay(funMusic, 10);         // 以前是一个错误

displayAndPlay(nightmareMusic, 0);    // 以前是一个错误

修改了灵巧指针类,包含了隐式类型转换操作符的成员函数模板以后,这个代码就可以成功运行了。拿如下调用举例,看看为什么能够成功运行:

displayAndPlay(funMusic, 10);

funMusic对象的类型是SmartPtr<Cassette>。函数displayAndPlay期望的参数是SmartPtr<MusicProduct>地对象。编译器侦测到类型不匹配并寻找把funMusic转换成SmartPtr<MusicProduct>对象的方法。它在SmartPtr<MusicProduct>类里寻找带有SmartPtr<Cassette>类型参数的单参数构造函数(参见条款5),但是没有找到。然后它们又寻找成员函数模板,能被实例化产生这样的函数。它们在SmartPtr<Cassette>发现了模板,把newType绑定到MusicProduct上,生成必须的函数。实例化函数,生成这样的代码:

SmartPtr<Cassette>::  operator SmartPtr<MusicProduct>()

{

  return SmartPtr<MusicProduct>(pointee);

}

能编译这行代码么?实际上这段代码就是用pointee做为参数调用SmartPtr<MusicProduct>的构造函数,所以真正的问题是能否用一个Cassette*指针构造一个SmartPtr<MusicProduct>对象,现在我们对dumb指针类型之间的转换已经很熟悉了,Cassette*能够被传递给需要MusicProduct*指针的地方。因此SmartPtr<MusicProduct>构造函数可以成功调用,同样SmartPtr<Cassette>SmartPtr<MusicProduct>之间的类型转换也能成功进行。太棒了,实现了灵巧指针之间的类型转换,还有什么比这更简单么?

 而且,还有什么比这功能更强大么?不要被这个例子误导,而认为这种方法只能用于把指针在继承层次中向上进行类型转换。这种方法可以成功地用于任何合法的指针类型转换。如果你有dumb指针T1*和另一种dumb指针T2*,当且仅当你能隐式地把T1*转换为T2*时,你就能够隐式地把指向T1的灵巧指针类型转换为指向T2的灵巧指针类型。

posted on 2007-05-26 09:23:00 by peon  评论(0) 阅读(666)

 
     译者注:由于我无法在文档区贴上图片(在论坛询问,结果无人回答),所以只能附上此译文的word文档。下载

这种技术能给我们几乎所有想要的行为特性。假设我们用一个新类CasSingle来扩充MusicProduct类层次,用来表示cassette singles。修改后的类层次看起来象这样:

现在考虑这段代码:

template<class T>                    // 同上, 包括作为类型
class SmartPtr { ... };              // 转换操作符的成员模板
 
void displayAndPlay(const SmartPtr<MusicProduct>& pmp,
                    int howMany);
 
void displayAndPlay(const SmartPtr<Cassette>& pc,
                    int howMany);
 
SmartPtr<CasSingle> dumbMusic(new CasSingle("Achy Breaky Heart"));
 
displayAndPlay(dumbMusic, 1);        // 错误!

在这个例子里,displayAndPlay被重载,一个函数带有SmartPtr<Cassette> 对象参数,其它函数的参数为SmartPtr<CasSingle>,我们期望调用SmartPtr<Cassette>,因为CasSingle是直接从Cassette上继承下来的,而它仅仅是间接继承自MusicProduct。当然这是dumb指针的工作方法,我们的灵巧指针不会这么灵巧。它们把成员函数做为转换操作符来使用,就C++编译器而言,所有类型转换操作符都一样,没有好坏的分别。因此displayAndPlay的调用具有二义性,因为从SmartPtr<CasSingle> SmartPtr<Cassette>的类型转换并不比到SmartPtr<MusicProduct>的类型转换好。

通过成员模板来实现灵巧指针的类型转换有还有两个缺点。第一,支持成员模板的编译器较少,所以这种技术不具有可移植性。以后情况会有所改观,但是没有人知道这会等到什么时候。第二,这种方法的工作原理不很明了,要理解它必须先要深入理解函数调用的参数匹配,隐式类型转换函数,模板函数隐式实例化和成员函数模板。有些程序员以前从来没有看到过这种技巧,而却被要求维护使用这种技巧的代码,我真是很可怜他们。这种技巧确实很巧妙,这自然是肯定,但是过于的巧妙可是一件危险的事情。

不要再拐弯抹角了,直接了当地说,我们想要知道的是在继承类向基类进行类型转换方面,我们如何能够让灵巧指针的行为与dumb指针一样呢?答案很简单:不可能。正如Daniel Edelson所说,灵巧指针固然灵巧,但不是指针。最好的方法是使用成员模板生成类型转换函数,在会产生二义性结果的地方使用casts(参见条款2)。这不是一个完美的方法,不过也很不错,在一些情况下去除二义性,所付出的代价与灵巧指针提供复杂的功能相比还是值得的。

灵巧指针和const

对于dumb指针来说,const既可以针对指针所指向的东西,也可以针对于指针本身,或者兼有两者的含义(参见Effective C++条款21):

CD goodCD("Flood");
 
const CD *p;                         // p 是一个non-const 指针
                                     //指向 const CD 对象
 
CD * const p = &goodCD;              // p 是一个const 指针 
                                     // 指向non-const CD 对象;
                                     // 因为 p const, 
                                     // 必须被初始化
 
const CD * const p = &goodCD;        // p 是一个const 指针
                                     // 指向一个 const CD 对象

我们自然想要让灵巧指针具有同样的灵活性。不幸的是只能在一个地方放置const,并只能对指针本身起作用,而不能针对于所指对象:

const SmartPtr<CD> p =                // p 是一个const 灵巧指针

  &goodCD;                             // 指向 non-const CD 对象

好像有一个简单的补救方法,就是建立一个指向cosnt CD的灵巧指针:

SmartPtr<const CD> p =            // p 是一个 non-const 灵巧指针
  &goodCD;                        // 指向const CD 对象
现在我们可以建立constnon-const对象和指针的四种不同组合:
SmartPtr<CD> p;                          // non-const 对象
                                         // non-const 指针
 
SmartPtr<const CD> p;                    // const 对象,
                                         // non-const 指针
 
const SmartPtr<CD> p = &goodCD;          // non-const 对象
                                         // const指针
 
const SmartPtr<const CD> p = &goodCD;    // const 对象
                                         // const 指针
 

但是美中不足的是,使用dumb指针我们能够用non-const指针初始化const指针,我们也能用指向non-cosnt对象的指针初始化指向const对象的指针;就像进行赋值一样。例如:

CD *pCD = new CD("Famous Movie Themes");
 
const CD * pConstCD = pCD;               // 正确

但是如果我们试图把这种方法用在灵巧指针上,情况会怎么样呢?

SmartPtr<CD> pCD = new CD("Famous Movie Themes");
 
SmartPtr<const CD> pConstCD = pCD;       // 正确么?

SmartPtr<CD> SmartPtr<const CD>是完全不同的类型。在编译器看来,它们是毫不相关的,所以没有理由相信它们是赋值兼容的。到目前为止这是一个老问题了,把它们变成赋值兼容的惟一方法是你必须提供函数,用来把SmartPtr<CD>类型的对象转换成SmartPtr<const CD>类型。如果你使用的编译器支持成员模板,就可以利用前面所说的技巧自动生成你需要的隐式类型转换操作。(我前面说过,只要对应的dumb指针能进行类型转换,灵巧指针也就能进行类型转换,我没有欺骗你们。包含const类型转换也没有问题。)如果你没有这样的编译器,你必须克服更大的困难。

包括const的类型转换是单向的:从non-constconst的转换是安全的,但是从constnon-const则不是安全的。而且用const指针能的事情,用non-const指针也能做,但是用non-const指针还能做其它一些事情(例如,赋值操作)。同样,用指向const的指针能做的任何事情,用指向non-const的指针也能做到,但是用指向non-const的指针能够完成一些使用指向const的指针所不能完成的事情(例如,赋值操作)。

这些规则看起来与public继承的规则相类似(Effective C++ 条款35)。你能够把一个派生类对象转换成基类对象,但是反之则不是这样,你对基类所做的任何事情对派生类也能做,但是还能对派生类做另外一些事情。我们能够利用这一点来实作灵巧指针,就是说可以让每个指向T的灵巧指针类public派生自一个对应的指向const-T的灵巧指针类:

template<class T>                    // 指向const对象的
class SmartPtrToConst {              // 灵巧指针
 
  ...                                // 灵巧指针通常的
                                     // 成员函数
 
protected:
  union {
    const T* constPointee;           //  SmartPtrToConst 访问
    T* pointee;                      //  SmartPtr 访问
  };
};
 
template<class T>                    // 指向non-const对象
class SmartPtr:                      // 的灵巧指针
  public SmartPtrToConst<T> {
  ...                                // 没有数据成员
};

使用这种设计方法,指向non-const-T对象的灵巧指针包含一个指向const-Tdumb指针,指向const-T的灵巧指针需要包含一个指向cosnt-Tdumb指针。最方便的方法是把指向const-Tdumb指针放在基类里,把指向non-const-Tdumb指针放在派生类里,然而这样做有些浪费,因为SmartPtr对象包含两个dumb指针:一个是从SmartPtrToConst继承来的,一个是SmartPtr自己的。

一种在C世界里的老式武器可以解决这个问题,这就是union,它在C++中同样有用。Unionprotected中,所以两个类都可以访问它,它包含两个必须的dumb指针类型,SmartPtrToConst<T>对象使用constPointee指针,SmartPtr<T>对象使用pointee指针。因此我们可以在不分配额外空间的情况下,使用两个不同的指针(参见Effective C++条款10中另外一个例子)这就是union美丽的地方。当然两个类的成员函数必须约束它们自己仅仅使用适合的指针。这是使用union所冒的风险。

利用这种新设计,我们能够获得所要的行为特性:

SmartPtr<CD> pCD = new CD("Famous Movie Themes");
 
SmartPtrToConst<CD> pConstCD = pCD;     // 正确
 

评价

有关灵巧指针的讨论该结束了,在我们离开这个话题之前,应该问这样一个问题:灵巧指针如此繁琐麻烦,是否值得使用,特别是如果你的编译器缺乏支持成员函数模板时。

经常是值得的。例如通过使用灵巧指针极大地简化了条款29中的引用计数代码。而且正如该例子所显示的,灵巧指针的使用在一些领域受到极大的限制,例如测试空值、转换到dumb指针、继承类向基类转换和对指向const的指针的支持。同时灵巧指针的实作、理解和维护需要大量的技巧。Debug使用灵巧指针的代码也比Debug使用dumb指针的代码困难。无论如何你也不可能设计出一种通用目的的灵巧指针,能够替代dumb指针。

达到同样的代码效果,使用灵巧指针更方便。灵巧指针应该谨慎使用, 不过每个C++程序员最终都会发现它们是有用的。

posted on 2007-05-26 09:22:00 by peon  评论(0) 阅读(623)

 
2007年05月24日



韦氏在线词典 在线金山词霸
 
 
剑桥在线词典 牛津在线词典
 
 
朗文在线词典 牛津高阶英汉双解在线词典
 
 
同义词在线词典 反义词在线词典
 
 



总列表

翻译类字典辞典

英汉类字典辞典

金山词霸在线版 —— 国人自主开发的最权威的电子词典,词霸搜索-免费在线词典查词翻译_英汉_日汉_英语_成语
百度词典搜索—— 百度词典搜索支持强大的英汉互译功能,中文成语的智能翻译
Yahoo学生英汉字典 —— 英语单词查询、举例
Dict_CN 在线词典 —— 在线搜索不重复汉英词条100万,英汉词条103万。
牛津英汉双解词典
顏氏美語 —— 颜元叔教授主编-网路英英/英汉辞典
 
中国专家翻译网—— 英文翻译公司--日文翻译公司--多语种翻译公司- 英语、日语、德语、法语翻译
中国译典@中国在线翻译网 —— 线上最庞大的英汉-汉英翻译语料库
『中国百帆』智能在线翻译系统
金桥翻译中心 _WWW_NETAT_NET
Free Website Translator - Online Website Translation 网页翻译

汉英类字典辞典

在线汉英双解新华字典
林语堂当代汉英词典(繁) —— 较权威的在线汉英词典,繁体,备有汉字部首索引和汉语拼音检索功能
华翼翻译-多语种在线电脑字典
太阳雨英汉\汉英词典 汉语输入方式:拼音、简体繁体
洪恩双语词典 中英文查询,提供词义、例句、词组、同义词、反义词

英文类字典辞典

朗文英语辞典
韦氏英语辞典
English Dictionary from freesearch_co_uk —— 例句不错
LEO English-German Dictionary —— 英文、德文互译在线词典,英文界面
Wordsmyth —— 美国英语,有难易之分
Latin-English Dictionary —— 在线拉丁语和英语词典,历史较久,英文界面
Webster's Collegiate Dictionary —— 著名的韦氏大词典在线版,使用方便,英文词汇多
American Sign Language Dictionary —— 美国形体语言词典,独特的在线词典
Dictionary.com—— 查询、互译、流行词汇、站点导航,英文
Thesaurus.com
—— 英语同义词字典,英文
LEO English-German Dictionary 英文、德文互译在线词典,英文界面
Onelook Dictionary 英语、法语、德语、意大利语五种语言629本词典的在线检索,权威,英文
Latin-English Dictionary 在线拉丁语和英语词典,历史较久,英文界面 
Travlang's Translating Dictionaries 欧洲主要语言互译,很多链接资源,英文
American Sign Language Dictionary 美国形体语言词典,独特的在线词典 
Oxford English Dictionary 牛津英语大词典在线版,须注册才能使用,英文
剑桥在线辞典 —— 包括剑桥国际英语辞典、美国英语辞典、国际短语辞典及国际习语辞典,英文
Thesaurus.com 英语同义词字典,英文
ANTONYM Finder and SYNONYM Thesaurus —— 同义词反义词词典

其他语言类字典辞典

日英 日韓 日中 - infoseek マルチ翻訳
德汉字典网
华翼电脑字典 —— 荷兰语、中文、英语、法语、 ...
线索中国 - 网上字典
承隆科技 
face=Arial>Amasoft
線上、離線英漢翻譯軟體,英漢/漢英字典 
颜元叔教授主编-网路英英/英汉辞典
DictionaryHK.com 提供英文对英文、中文和日文的翻译。
纳西东巴象形文字纳汉在线字典 - 提供汉字与东巴象形文字在线翻译工具。 
YourDictionary.com —— 几十个语种和数百本词典的在线检索,最权威的在线词典门户之一,英文界面
法汉汉法词典 —— 法语 汉语 在线 词典
西班牙语汉语
 
汉语类字典辞典

解字类字典辞典

中华在线词典 —— 12部在线汉语词典免费使用
在线汉语字典
引经据典
中文字谱
—— 为学汉语的外国人所设,有英汉对照分析汉字的由来、汉字发音、象形文字、英汉索引
字典网
—— 国语辞典、台语辞典、中文字典、中文字谱、JDIC等

成语类字典辞典

成语词典 —— 金石网
在线成语大字典
中华成语网上字典
瓷都成语知识系统

诗词类字典辞典

中华诗词 —— 共收录了4577位诗词作家61981首作品
稻香居电脑作诗机网络版 —— 包含电脑智能作诗(填词),电脑辅助作诗(填词),电脑诗词游戏三个部分
A Chinese-Cantonese Syllabary - 黄锡凌《粤音韵汇》 ... [ 繁体]
 
 
专业类字典辞典

缩写类字典辞典

常用缩写
电脑术语与缩写
世界各国和地区名称代码表(标准代码,国际域名缩写)
行业代码表
Acronym Finder —— (英)收錄408,000縮寫頭字語款目,主題包括電腦、科技、電訊和軍事方面

百科类字典辞典

大英百科全书 —— (英)著名的百科全书
维基百科 —— 维基百科,自由的百科全书

法律类字典辞典

尚华法律 —— 深圳律师咨询、聘请律师、深圳律师培训、律师邮局、律师建站
法律与经济学资料库 —— 综合性的经贸与法律大辞典,可按类别和题目搜索
Duhaime's Law Dictionary ——(英)

金融类字典辞典

巴克利金融术语汇编 —— 简单易学的金融术语辞典
金融专业术语大辞典 —— 有些词很难找,是不是,来我们这儿试试吧!
中國經貿新詞詞典 —— 香港贸发局维护的经贸词典
交易商必备辞典 —— 完整地收集了交易中可能用到的各种专业术语

医药类字典辞典

英汉医学词典 —— 大型英汉医学词典
药品字典

计算机类字典辞典

英汉计算机及网络通讯技术词汇
CNPedia 华文电脑百科
趨勢科技-病毒百科
Encyberpedia Dictionary and Glossary —— (英文)因特网上主要的字典和词汇一览表,
On-line Dictionary of Computing —— 计算机专业词典,英文
ComputerUser_com High-Tech Dictionary
Whatis_com, the leading IT encyclopedia and learning center

科技类字典辞典

郑州大学在线英汉-汉英科技大词典 —— 本词典固定词库中现收录英汉科技词语490269条,汉英科技词语744542条
高技术辞典网

其他类字典辞典

中国水灾年表 —— 中国历史各年水灾灾情、损失等介绍
植物病理学在线术语汇编 [English] —— 详细的带有解说的大辞典,其中收集了植物病理学的专业术语及其发音
土木建筑电子词典 —— 台湾國科會科學技術資料中心國內資源組维护
包装词汇英汉对照 —— 有关包装词汇的英汉对照词库,约29000条
英汉电子工程辞典
宗教小词典
涉藏汉英词汇字典
Movie Terminology Glossary —— 电影专业术语辞典
化工字典 —— 现有词汇量 300,000 条
化工字典 _ 中国试剂信息网 —— 现有词汇量351681条。其中包含CAS编号的有246435条
纺织字典 —— 收录有关纺织方面的词汇量高达 2,5000 多条
纺织字典 —— 共收录了30,000条与纺织有关的词汇
第五代简体仓颉字典
繁体仓颉字典
泵阀字典 —— 收录有关泵阀方面的词汇量高达 20,000 多条

posted on 2007-05-24 10:21:00 by peon  评论(0) 阅读(1230)

 
2007年05月22日
       2       3       5       7      11      13      17      19      23      29
      31      37      41      43      47      53      59      61      67      71
      73      79      83      89      97     101     103     107     109     113
     127     131     137     139     149     151     157     163     167     173
     179     181     191     193     197     199     211     223     227     229
     233     239     241     251     257     263     269     271     277     281
     283     293     307     311     313     317     331     337     347     349
     353     359     367     373     379     383     389     397     401     409
     419     421     431     433     439     443     449     457     461     463
     467     479     487     491     499     503     509     521     523     541
     547     557     563     569     571     577     587     593     599     601
     607     613     617     619     631     641     643     647     653     659
     661     673     677     683     691     701     709     719     727     733
     739     743     751     757     761     769     773     787     797     809
     811     821     823     827     829     839     853     857     859     863
     877     881     883     887     907     911     919     929     937     941
     947     953     967     971     977     983     991     997    1009    1013
    1019    1021    1031    1033    1039    1049    1051    1061    1063    1069
    1087    1091    1093    1097    1103    1109    1117    1123    1129    1151
    1153    1163    1171    1181    1187    1193    1201    1213    1217    1223
    1229    1231    1237    1249    1259    1277    1279    1283    1289    1291
    1297    1301    1303    1307    1319    1321    1327    1361    1367    1373
    1381    1399    1409    1423    1427    1429    1433    1439    1447    1451
    1453    1459    1471    1481    1483    1487    1489    1493    1499    1511
    1523    1531    1543    1549    1553    1559    1567    1571    1579    1583
    1597    1601    1607    1609    1613    1619    1621    1627    1637    1657
    1663    1667    1669    1693    1697    1699    1709    1721    1723    1733
    1741    1747    1753    1759    1777    1783    1787    1789    1801    1811
    1823    1831    1847    1861    1867    1871    1873    1877    1879    1889
    1901    1907    1913    1931    1933    1949    1951    1973    1979    1987
    1993    1997    1999    2003    2011    2017    2027    2029    2039    2053
    2063    2069    2081    2083    2087    2089    2099    2111    2113    2129
    2131    2137    2141    2143    2153    2161    2179    2203    2207    2213
    2221    2237    2239    2243    2251    2267    2269    2273    2281    2287
    2293    2297    2309    2311    2333    2339    2341    2347    2351    2357
    2371    2377    2381    2383    2389    2393    2399    2411    2417    2423
    2437    2441    2447    2459    2467    2473    2477    2503    2521    2531
    2539    2543    2549    2551    2557    2579    2591    2593    2609    2617
    2621    2633    2647    2657    2659    2663    2671    2677    2683    2687
    2689    2693    2699    2707    2711    2713    2719    2729    2731    2741
    2749    2753    2767    2777    2789    2791    2797    2801    2803    2819
    2833    2837    2843    2851    2857    2861    2879    2887    2897    2903
    2909    2917    2927    2939    2953    2957    2963    2969    2971    2999
    3001    3011    3019    3023    3037    3041    3049    3061    3067    3079
    3083    3089    3109    3119    3121    3137    3163    3167    3169    3181
    3187    3191    3203    3209    3217    3221    3229    3251    3253    3257
    3259    3271    3299    3301    3307    3313    3319    3323    3329    3331
    3343    3347    3359    3361    3371    3373    3389    3391    3407    3413
    3433    3449    3457    3461    3463    3467    3469    3491    3499    3511
    3517    3527    3529    3533    3539    3541    3547    3557    3559    3571
    3581    3583    3593    3607    3613    3617    3623    3631    3637    3643
    3659    3671    3673    3677    3691    3697    3701    3709    3719    3727
    3733    3739    3761    3767    3769    3779    3793    3797    3803    3821
    3823    3833    3847    3851    3853    3863    3877    3881    3889    3907
    3911    3917    3919    3923    3929    3931    3943    3947    3967    3989
    4001    4003    4007    4013    4019    4021    4027    4049    4051    4057
    4073    4079    4091    4093    4099    4111    4127    4129    4133    4139
    4153    4157    4159    4177    4201    4211    4217    4219    4229    4231
    4241    4243    4253    4259    4261    4271    4273    4283    4289    4297
    4327    4337    4339    4349    4357    4363    4373    4391    4397    4409
    4421    4423    4441    4447    4451    4457    4463    4481    4483    4493
    4507    4513    4517    4519    4523    4547    4549    4561    4567    4583
    4591    4597    4603    4621    4637    4639    4643    4649    4651    4657
    4663    4673    4679    4691    4703    4721    4723    4729    4733    4751
    4759    4783    4787    4789    4793    4799    4801    4813    4817    4831
    4861    4871    4877    4889    4903    4909    4919    4931    4933    4937
    4943    4951    4957    4967    4969    4973    4987    4993    4999    5003
    5009    5011    5021    5023    5039    5051    5059    5077    5081    5087
    5099    5101    5107    5113    5119    5147    5153    5167    5171    5179
    5189    5197    5209    5227    5231    5233    5237    5261    5273    5279
    5281    5297    5303    5309    5323    5333    5347    5351    5381    5387
    5393    5399    5407    5413    5417    5419    5431    5437    5441    5443
    5449    5471    5477    5479    5483    5501    5503    5507    5519    5521
    5527    5531    5557    5563    5569    5573    5581    5591    5623    5639
    5641    5647    5651    5653    5657    5659    5669    5683    5689    5693
    5701    5711    5717    5737    5741    5743    5749    5779    5783    5791
    5801    5807    5813    5821    5827    5839    5843    5849    5851    5857
    5861    5867    5869    5879    5881    5897    5903    5923    5927    5939
    5953    5981    5987    6007    6011    6029    6037    6043    6047    6053
    6067    6073    6079    6089    6091    6101    6113    6121    6131    6133
    6143    6151    6163    6173    6197    6199    6203    6211    6217    6221
    6229    6247    6257    6263    6269    6271    6277    6287    6299    6301
    6311    6317    6323    6329    6337    6343    6353    6359    6361    6367
    6373    6379    6389    6397    6421    6427    6449    6451    6469    6473
    6481    6491    6521    6529    6547    6551    6553    6563    6569    6571
    6577    6581    6599    6607    6619    6637    6653    6659    6661    6673
    6679    6689    6691    6701    6703    6709    6719    6733    6737    6761
    6763    6779    6781    6791    6793    6803    6823    6827    6829    6833
    6841    6857    6863    6869    6871    6883    6899    6907    6911    6917
    6947    6949    6959    6961    6967    6971    6977    6983    6991    6997
    7001    7013    7019    7027    7039    7043    7057    7069    7079    7103
    7109    7121    7127    7129    7151    7159    7177    7187    7193    7207
    7211    7213    7219    7229    7237    7243    7247    7253    7283    7297
    7307    7309    7321    7331    7333    7349    7351    7369    7393    7411
    7417    7433    7451    7457    7459    7477    7481    7487    7489    7499
    7507    7517    7523    7529    7537    7541    7547    7549    7559    7561
    7573    7577    7583    7589    7591    7603    7607    7621    7639    7643
    7649    7669    7673    7681    7687    7691    7699    7703    7717    7723
    7727    7741    7753    7757    7759    7789    7793    7817    7823    7829
    7841    7853    7867    7873    7877    7879    7883    7901    7907    7919
    7927    7933    7937    7949    7951    7963    7993    8009    8011    8017
    8039    8053    8059    8069    8081    8087    8089    8093    8101    8111
    8117    8123    8147    8161    8167    8171    8179    8191    8209    8219
    8221    8231    8233    8237    8243    8263    8269    8273    8287    8291
    8293    8297    8311    8317    8329    8353    8363    8369    8377    8387
    8389    8419    8423    8429    8431    8443    8447    8461    8467    8501
    8513    8521    8527    8537    8539    8543    8563    8573    8581    8597
    8599    8609    8623    8627    8629    8641    8647    8663    8669    8677
    8681    8689    8693    8699    8707    8713    8719    8731    8737    8741
    8747    8753    8761    8779    8783    8803    8807    8819    8821    8831
    8837    8839    8849    8861    8863    8867    8887    8893    8923    8929
    8933    8941    8951    8963    8969    8971    8999    9001    9007    9011
    9013    9029    9041    9043    9049    9059    9067    9091    9103    9109
    9127    9133    9137    9151    9157    9161    9173    9181    9187    9199
    9203    9209    9221    9227    9239    9241    9257    9277    9281    9283
    9293    9311    9319    9323    9337    9341    9343    9349    9371    9377
    9391    9397    9403    9413    9419    9421    9431    9433    9437    9439
    9461    9463    9467    9473    9479    9491    9497    9511    9521    9533
    9539    9547    9551    9587    9601    9613    9619    9623    9629    9631
    9643    9649    9661    9677    9679    9689    9697    9719    9721    9733
    9739    9743    9749    9767    9769    9781    9787    9791    9803    9811
    9817    9829    9833    9839    9851    9857    9859    9871    9883    9887
    9901    9907    9923    9929    9931    9941    9949    9967    9973   10007
   10009   10037   10039   10061   10067   10069   10079   10091   10093   10099
   10103   10111   10133   10139   10141   10151   10159   10163   10169   10177
   10181   10193   10211   10223   10243   10247   10253   10259   10267   10271
   10273   10289   10301   10303   10313   10321   10331   10333   10337   10343
   10357   10369   10391   10399   10427   10429   10433   10453   10457   10459
   10463   10477   10487   10499   10501   10513   10529   10531   10559   10567
   10589   10597   10601   10607   10613   10627   10631   10639   10651   10657
   10663   10667   10687   10691   10709   10711   10723   10729   10733   10739
   10753   10771   10781   10789   10799   10831   10837   10847   10853   10859
   10861   10867   10883   10889   10891   10903   10909   10937   10939   10949
   10957   10973   10979   10987   10993   11003   11027   11047   11057   11059
   11069   11071   11083   11087   11093   11113   11117   11119   11131   11149
   11159   11161   11171   11173   11177   11197   11213   11239   11243   11251
   11257   11261   11273   11279   11287   11299   11311   11317   11321   11329
   11351   11353   11369   11383   11393   11399   11411   11423   11437   11443
   11447   11467   11471   11483   11489   11491   11497   11503   11519   11527
   11549   11551   11579   11587   11593   11597   11617   11621   11633   11657
   11677   11681   11689   11699   11701   11717   11719   11731   11743   11777
   11779   11783   11789   11801   11807   11813   11821   11827   11831   11833
   11839   11863   11867   11887   11897   11903   11909   11923   11927   11933
   11939   11941   11953   11959   11969   11971   11981   11987   12007   12011
   12037   12041   12043   12049   12071   12073   12097   12101   12107   12109
   12113   12119   12143   12149   12157   12161   12163   12197   12203   12211
   12227   12239   12241   12251   12253   12263   12269   12277   12281   12289
   12301   12323   12329   12343   12347   12373   12377   12379   12391   12401
   12409   12413   12421   12433   12437   12451   12457   12473   12479   12487
   12491   12497   12503   12511   12517   12527   12539   12541   12547   12553
   12569   12577   12583   12589   12601   12611   12613   12619   12637   12641
   12647   12653   12659   12671   12689   12697   12703   12713   12721   12739
   12743   12757   12763   12781   12791   12799   12809   12821   12823   12829
   12841   12853   12889   12893   12899   12907   12911   12917   12919   12923
   12941   12953   12959   12967   12973   12979   12983   13001   13003   13007
   13009   13033   13037   13043   13049   13063   13093   13099   13103   13109
   13121   13127   13147   13151   13159   13163   13171   13177   13183   13187
   13217   13219   13229   13241   13249   13259   13267   13291   13297   13309
   13313   13327   13331   13337   13339   13367   13381   13397   13399   13411
   13417   13421   13441   13451   13457   13463   13469   13477   13487   13499
   13513   13523   13537   13553   13567   13577   13591   13597   13613   13619
   13627   13633   13649   13669   13679   13681   13687   13691   13693   13697
   13709   13711   13721   13723   13729   13751   13757   13759   13763   13781
   13789   13799   13807   13829   13831   13841   13859   13873   13877   13879
   13883   13901   13903   13907   13913   13921   13931   13933   13963   13967
   13997   13999   14009   14011   14029   14033   14051   14057   14071   14081
   14083   14087   14107   14143   14149   14153   14159   14173   14177   14197
   14207   14221   14243   14249   14251   14281   14293   14303   14321   14323
   14327   14341   14347   14369   14387   14389   14401   14407   14411   14419
   14423   14431   14437   14447   14449   14461   14479   14489   14503   14519
   14533   14537   14543   14549   14551   14557   14561   14563   14591   14593
   14621   14627   14629   14633   14639   14653   14657   14669   14683   14699
   14713   14717   14723   14731   14737   14741   14747   14753   14759   14767
   14771   14779   14783   14797   14813   14821   14827   14831   14843   14851
   14867   14869   14879   14887   14891   14897   14923   14929   14939   14947
   14951   14957   14969   14983   15013   15017   15031   15053   15061   15073
   15077   15083   15091   15101   15107   15121   15131   15137   15139   15149
   15161   15173   15187   15193   15199   15217   15227   15233   15241   15259
   15263   15269   15271   15277   15287   15289   15299   15307   15313   15319
   15329   15331   15349   15359   15361   15373   15377   15383   15391   15401
   15413   15427   15439   15443   15451   15461   15467   15473   15493   15497
   15511   15527   15541   15551   15559   15569   15581   15583   15601   15607
   15619   15629   15641   15643   15647   15649   15661   15667   15671   15679
   15683   15727   15731   15733   15737   15739   15749   15761   15767   15773
   15787   15791   15797   15803   15809   15817   15823   15859   15877   15881
   15887   15889   15901   15907   15913   15919   15923   15937   15959   15971
   15973   15991   16001   16007   16033   16057   16061   16063   16067   16069
   16073   16087   16091   16097   16103   16111   16127   16139   16141   16183
   16187   16189   16193   16217   16223   16229   16231   16249   16253   16267
   16273   16301   16319   16333   16339   16349   16361   16363   16369   16381
   16411   16417   16421   16427   16433   16447   16451   16453   16477   16481
   16487   16493   16519   16529   16547   16553   16561   16567   16573   16603
   16607   16619   16631   16633   16649   16651   16657   16661   16673   16691
   16693   16699   16703   16729   16741   16747   16759   16763   16787   16811
   16823   16829   16831   16843   16871   16879   16883   16889   16901   16903
   16921   16927   16931   16937   16943   16963   16979   16981   16987   16993
   17011   17021   17027   17029   17033   17041   17047   17053   17077   17093
   17099   17107   17117   17123   17137   17159   17167   17183   17189   17191
   17203   17207   17209   17231   17239   17257   17291   17293   17299   17317
   17321   17327   17333   17341   17351   17359   17377   17383   17387   17389
   17393   17401   17417   17419   17431   17443   17449   17467   17471   17477
   17483   17489   17491   17497   17509   17519   17539   17551   17569   17573
   17579   17581   17597   17599   17609   17623   17627   17657   17659   17669
   17681   17683   17707   17713   17729   17737   17747   17749   17761   17783
   17789   17791   17807   17827   17837   17839   17851   17863   17881   17891
   17903   17909   17911   17921   17923   17929   17939   17957   17959   17971
   17977   17981   17987   17989   18013   18041   18043   18047   18049   18059
   18061   18077   18089   18097   18119   18121   18127   18131   18133   18143
   18149   18169   18181   18191   18199   18211   18217   18223   18229   18233
   18251   18253   18257   18269   18287   18289   18301   18307   18311   18313
   18329   18341   18353   18367   18371   18379   18397   18401   18413   18427
   18433   18439   18443   18451   18457   18461   18481   18493   18503   18517
   18521   18523   18539   18541   18553   18583   18587   18593   18617   18637
   18661   18671   18679   18691   18701   18713   18719   18731   18743   18749
   18757   18773   18787   18793   18797   18803   18839   18859   18869   18899
   18911   18913   18917   18919   18947   18959   18973   18979   19001   19009
   19013   19031   19037   19051   19069   19073   19079   19081   19087   19121
   19139   19141   19157   19163   19181   19183   19207   19211   19213   19219
   19231   19237   19249   19259   19267   19273   19289   19301   19309   19319
   19333   19373   19379   19381   19387   19391   19403   19417   19421   19423
   19427   19429   19433   19441   19447   19457   19463   19469   19471   19477
   19483   19489   19501   19507   19531   19541   19543   19553   19559   19571
   19577   19583   19597   19603   19609   19661   19681   19687   19697   19699
   19709   19717   19727   19739   19751   19753   19759   19763   19777   19793
   19801   19813   19819   19841   19843   19853   19861   19867   19889   19891
   19913   19919   19927   19937   19949   19961   19963   19973   19979   19991
   19993   19997   20011   20021   20023   20029   20047   20051   20063   20071
   20089   20101   20107   20113   20117   20123   20129   20143   20147   20149
   20161   20173   20177   20183   20201   20219   20231   20233   20249   20261
   20269   20287   20297   20323   20327   20333   20341   20347   20353   20357
   20359   20369   20389   20393   20399   20407   20411   20431   20441   20443
   20477   20479   20483   20507   20509   20521   20533   20543   20549   20551
   20563   20593   20599   20611   20627   20639   20641   20663   20681   20693
   20707   20717   20719   20731   20743   20747   20749   20753   20759   20771
   20773   20789   20807   20809   20849   20857   20873   20879   20887   20897
   20899   20903   20921   20929   20939   20947   20959   20963   20981   20983
   21001   21011   21013   21017   21019   21023   21031   21059   21061   21067
   21089   21101   21107   21121   21139   21143   21149   21157   21163   21169
   21179   21187   21191   21193   21211   21221   21227   21247   21269   21277
   21283   21313   21317   21319   21323   21341   21347   21377   21379   21383
   21391   21397   21401   21407   21419   21433   21467   21481   21487   21491
   21493   21499   21503   21517   21521   21523   21529   21557   21559   21563
   21569   21577   21587   21589   21599   21601   21611   21613   21617   21647
   21649   21661   21673   21683   21701   21713   21727   21737   21739   21751
   21757   21767   21773   21787   21799   21803   21817   21821   21839   21841
   21851   21859   21863   21871   21881   21893   21911   21929   21937   21943
   21961   21977   21991   21997   22003   22013   22027   22031   22037   22039
   22051   22063   22067   22073   22079   22091   22093   22109   22111   22123
   22129   22133   22147   22153   22157   22159   22171   22189   22193   22229
   22247   22259   22271   22273   22277   22279   22283   22291   22303   22307
   22343   22349   22367   22369   22381   22391   22397   22409   22433   22441
   22447   22453   22469   22481   22483   22501   22511   22531   22541   22543
   22549   22567   22571   22573   22613   22619   22621   22637   22639   22643
   22651   22669   22679   22691   22697   22699   22709   22717   22721   22727
   22739   22741   22751   22769   22777   22783   22787   22807   22811   22817
   22853   22859   22861   22871   22877   22901   22907   22921   22937   22943
   22961   22963   22973   22993   23003   23011   23017   23021   23027   23029
   23039   23041   23053   23057   23059   23063   23071   23081   23087   23099
   23117   23131   23143   23159   23167   23173   23189   23197   23201   23203
   23209   23227   23251   23269   23279   23291   23293   23297   23311   23321
   23327   23333   23339   23357   23369   23371   23399   23417   23431   23447
   23459   23473   23497   23509   23531   23537   23539   23549   23557   23561
   23563   23567   23581   23593   23599   23603   23609   23623   23627   23629
   23633   23663   23669   23671   23677   23687   23689   23719   23741   23743
   23747   23753   23761   23767   23773   23789   23801   23813   23819   23827
   23831   23833   23857   23869   23873   23879   23887   23893   23899   23909
   23911   23917   23929   23957   23971   23977   23981   23993   24001   24007
   24019   24023   24029   24043   24049   24061   24071   24077   24083   24091
   24097   24103   24107   24109   24113   24121   24133   24137   24151   24169
   24179   24181   24197   24203   24223   24229   24239   24247   24251   24281
   24317   24329   24337   24359   24371   24373   24379   24391   24407   24413
   24419   24421   24439   24443   24469   24473   24481   24499   24509   24517
   24527   24533   24547   24551   24571   24593   24611   24623   24631   24659
   24671   24677   24683   24691   24697   24709   24733   24749   24763   24767
   24781   24793   24799   24809   24821   24841   24847   24851   24859   24877
   24889   24907   24917   24919   24923   24943   24953   24967   24971   24977
   24979   24989   25013   25031   25033   25037   25057   25073   25087   25097
   25111   25117   25121   25127   25147   25153   25163   25169   25171   25183
   25189   25219   25229   25237   25243   25247   25253   25261   25301   25303
   25307   25309   25321   25339   25343   25349   25357   25367   25373   25391
   25409   25411   25423   25439   25447   25453   25457   25463   25469   25471
   25523   25537   25541   25561   25577   25579   25583   25589   25601   25603
   25609   25621   25633   25639   25643   25657   25667   25673   25679   25693
   25703   25717   25733   25741   25747   25759   25763   25771   25793   25799
   25801   25819   25841   25847   25849   25867   25873   25889   25903   25913
   25919   25931   25933   25939   25943   25951   25969   25981   25997   25999
   26003   26017   26021   26029   26041   26053   26083   26099   26107   26111
   26113   26119   26141   26153   26161   26171   26177   26183   26189   26203
   26209   26227   26237   26249   26251   26261   26263   26267   26293   26297
   26309   26317   26321   26339   26347   26357   26371   26387   26393   26399
   26407   26417   26423   26431   26437   26449   26459   26479   26489   26497
   26501   26513   26539   26557   26561   26573   26591   26597   26627   26633
   26641   26647   26669   26681   26683   26687   26693   26699   26701   26711
   26713   26717   26723   26729   26731   26737   26759   26777   26783   26801
   26813   26821   26833   26839   26849   26861   26863   26879   26881   26891
   26893   26903   26921   26927   26947   26951   26953   26959   26981   26987
   26993   27011   27017   27031   27043   27059   27061   27067   27073   27077
   27091   27103   27107   27109   27127   27143   27179   27191   27197   27211
   27239   27241   27253   27259   27271   27277   27281   27283   27299   27329
   27337   27361   27367   27397   27407   27409   27427   27431   27437   27449
   27457   27479   27481   27487   27509   27527   27529   27539   27541   27551
   27581   27583   27611   27617   27631   27647   27653   27673   27689   27691
   27697   27701   27733   27737   27739   27743   27749   27751   27763   27767
   27773   27779   27791   27793   27799   27803   27809   27817   27823   27827
   27847   27851   27883   27893   27901   27917   27919   27941   27943   27947
   27953   27961   27967   27983   27997   28001   28019   28027   28031   28051
   28057   28069   28081   28087   28097   28099   28109   28111   28123   28151
   28163   28181   28183   28201   28211   28219   28229   28277   28279   28283
   28289   28297   28307   28309   28319   28349   28351   28387   28393   28403
   28409   28411   28429   28433   28439   28447   28463   28477   28493   28499
   28513   28517   28537   28541   28547   28549   28559   28571   28573   28579
   28591   28597   28603   28607   28619   28621   28627   28631   28643   28649
   28657   28661   28663   28669   28687   28697   28703   28711   28723   28729
   28751   28753   28759   28771   28789   28793   28807   28813   28817   28837
   28843   28859   28867   28871   28879   28901   28909   28921   28927   28933
   28949   28961   28979   29009   29017   29021   29023   29027   29033   29059
   29063   29077   29101   29123   29129   29131   29137   29147   29153   29167
   29173   29179   29191   29201   29207   29209   29221   29231   29243   29251
   29269   29287   29297   29303   29311   29327   29333   29339   29347   29363
   29383   29387   29389   29399   29401   29411   29423   29429   29437   29443
   29453   29473   29483   29501   29527   29531   29537   29567   29569   29573
   29581   29587   29599   29611   29629   29633   29641   29663   29669   29671
   29683   29717   29723   29741   29753   29759   29761   29789   29803   29819
   29833   29837   29851   29863   29867   29873   29879   29881   29917   29921
   29927   29947   29959   29983   29989   30011   30013   30029   30047   30059
   30071   30089   30091   30097   30103   30109   30113   30119   30133   30137
   30139   30161   30169   30181   30187   30197   30203   30211   30223   30241
   30253   30259   30269   30271   30293   30307   30313   30319   30323   30341
   30347   30367   30389   30391   30403   30427   30431   30449   30467   30469
   30491   30493   30497   30509   30517   30529   30539   30553   30557   30559
   30577   30593   30631   30637   30643   30649   30661   30671   30677   30689
   30697   30703   30707   30713   30727   30757   30763   30773   30781   30803
   30809   30817   30829   30839   30841   30851   30853   30859   30869   30871
   30881   30893   30911   30931   30937   30941   30949   30971   30977   30983
   31013   31019   31033   31039   31051   31063   31069   31079   31081   31091
   31121   31123   31139   31147   31151   31153   31159   31177   31181   31183
   31189   31193   31219   31223   31231   31237   31247   31249   31253   31259
   31267   31271   31277   31307   31319   31321   31327   31333   31337   31357
   31379   31387   31391   31393   31397   31469   31477   31481   31489   31511
   31513   31517   31531   31541   31543   31547   31567   31573   31583   31601
   31607   31627   31643   31649   31657   31663   31667   31687   31699   31721
   31723   31727   31729   31741   31751   31769   31771   31793   31799   31817
   31847   31849   31859   31873   31883   31891   31907   31957   31963   31973
   31981   31991   32003   32009   32027   32029   32051   32057   32059   32063
   32069   32077   32083   32089   32099   32117   32119   32141   32143   32159
   32173   32183   32189   32191   32203   32213   32233   32237   32251   32257
   32261   32297   32299   32303   32309   32321   32323   32327   32341   32353
   32359   32363   32369   32371   32377   32381   32401   32411   32413   32423
   32429   32441   32443   32467   32479   32491   32497   32503   32507   32531
   32533   32537   32561   32563   32569   32573   32579   32587   32603   32609
   32611   32621   32633   32647   32653   32687   32693   32707   32713   32717
   32719   32749   32771   32779   32783   32789   32797   32801   32803   32831
   32833   32839   32843   32869   32887   32909   32911   32917   32933   32939
   32941   32957   32969   32971   32983   32987   32993   32999   33013   33023
   33029   33037   33049   33053   33071   33073   33083   33091   33107   33113
   33119   33149   33151   33161   33179   33181   33191   33199   33203   33211
   33223   33247   33287   33289   33301   33311   33317   33329   33331   33343
   33347   33349   33353   33359   33377   33391   33403   33409   33413   33427
   33457   33461   33469   33479   33487   33493   33503   33521   33529   33533
   33547   33563   33569   33577   33581   33587   33589   33599   33601   33613
   33617   33619   33623   33629   33637   33641   33647   33679   33703   33713
   33721   33739   33749   33751   33757   33767   33769   33773   33791   33797
   33809   33811   33827   33829   33851   33857   33863   33871   33889   33893
   33911   33923   33931   33937   33941   33961   33967   33997   34019   34031
   34033   34039   34057   34061   34123   34127   34129   34141   34147   34157
   34159   34171   34183   34211   34213   34217   34231   34253   34259   34261
   34267   34273   34283   34297   34301   34303   34313   34319   34327   34337
   34351   34361   34367   34369   34381   34403   34421   34429   34439   34457
   34469   34471   34483   34487   34499   34501   34511   34513   34519   34537
   34543   34549   34583   34589   34591   34603   34607   34613   34631   34649
   34651   34667   34673   34679   34687   34693   34703   34721   34729   34739
   34747   34757   34759   34763   34781   34807   34819   34841   34843   34847
   34849   34871   34877   34883   34897   34913   34919   34939   34949   34961
   34963   34981   35023   35027   35051   35053   35059   35069   35081   35083
   35089   35099   35107   35111   35117   35129   35141   35149   35153   35159
   35171   35201   35221   35227   35251   35257   35267   35279   35281   35291
   35311   35317   35323   35327   35339   35353   35363   35381   35393   35401
   35407   35419   35423   35437   35447   35449   35461   35491   35507   35509
   35521   35527   35531   35533   35537   35543   35569   35573   35591   35593
   35597   35603   35617   35671   35677   35729   35731   35747   35753   35759
   35771   35797   35801   35803   35809   35831   35837   35839   35851   35863
   35869   35879   35897   35899   35911   35923   35933   35951   35963   35969
   35977   35983   35993   35999   36007   36011   36013   36017   36037   36061
   36067   36073   36083   36097   36107   36109   36131   36137   36151   36161
   36187   36191   36209   36217   36229   36241   36251   36263   36269   36277
   36293   36299   36307   36313   36319   36341   36343   36353   36373   36383
   36389   36433   36451   36457   36467   36469   36473   36479   36493   36497
   36523   36527   36529   36541   36551   36559   36563   36571   36583   36587
   36599   36607   36629   36637   36643   36653   36671   36677   36683   36691
   36697   36709   36713   36721   36739   36749   36761   36767   36779   36781
   36787   36791   36793   36809   36821   36833   36847   36857   36871   36877
   36887   36899   36901   36913   36919   36923   36929   36931   36943   36947
   36973   36979   36997   37003   37013   37019   37021   37039   37049   37057
   37061   37087   37097   37117   37123   37139   37159   37171   37181   37189
   37199   37201   37217   37223   37243   37253   37273   37277   37307   37309
   37313   37321   37337   37339   37357   37361   37363   37369   37379   37397
   37409   37423   37441   37447   37463   37483   37489   37493   37501   37507
   37511   37517   37529   37537   37547   37549   37561   37567   37571   37573
   37579   37589   37591   37607   37619   37633   37643   37649   37657   37663
   37691   37693   37699   37717   37747   37781   37783   37799   37811   37813
   37831   37847   37853   37861   37871   37879   37889   37897   37907   37951
   37957   37963   37967   37987   37991   37993   37997   38011   38039   38047
   38053   38069   38083   38113   38119   38149   38153   38167   38177   38183
   38189   38197   38201   38219   38231   38237   38239   38261   38273   38281
   38287   38299   38303   38317   38321   38327   38329   38333   38351   38371
   38377   38393   38431   38447   38449   38453   38459   38461   38501   38543
   38557   38561   38567   38569   38593   38603   38609   38611   38629   38639
   38651   38653   38669   38671   38677   38693   38699   38707   38711   38713
   38723   38729   38737   38747   38749   38767   38783   38791   38803   38821
   38833   38839   38851   38861   38867   38873   38891   38903   38917   38921
   38923   38933   38953   38959   38971   38977   38993   39019   39023   39041
   39043   39047   39079   39089   39097   39103   39107   39113   39119   39133
   39139   39157   39161   39163   39181   39191   39199   39209   39217   39227
   39229   39233   39239   39241   39251   39293   39301   39313   39317   39323
   39341   39343   39359   39367   39371   39373   39383   39397   39409   39419
   39439   39443   39451   39461   39499   39503   39509   39511   39521   39541
   39551   39563   39569   39581   39607   39619   39623   39631   39659   39667
   39671   39679   39703   39709   39719   39727   39733   39749   39761   39769
   39779   39791   39799   39821   39827   39829   39839   39841   39847   39857
   39863   39869   39877   39883   39887   39901   39929   39937   39953   39971
   39979   39983   39989   40009   40013   40031   40037   40039   40063   40087
   40093   40099   40111   40123   40127   40129   40151   40153   40163   40169
   40177   40189   40193   40213   40231   40237   40241   40253   40277   40283
   40289   40343   40351   40357   40361   40387   40423   40427   40429   40433
   40459   40471   40483   40487   40493   40499   40507   40519   40529   40531
   40543   40559   40577   40583   40591   40597   40609   40627   40637   40639
   40693   40697   40699   40709   40739   40751   40759   40763   40771   40787
   40801   40813   40819   40823   40829   40841   40847   40849   40853   40867
   40879   40883   40897   40903   40927   40933   40939   40949   40961   40973
   40993   41011   41017   41023   41039   41047   41051   41057   41077   41081
   41113   41117   41131   41141   41143   41149   41161   41177   41179   41183
   41189   41201   41203   41213   41221   41227   41231   41233   41243   41257
   41263   41269   41281   41299   41333   41341   41351   41357   41381   41387
   41389   41399   41411   41413   41443   41453   41467   41479   41491   41507
   41513   41519   41521   41539   41543   41549   41579   41593   41597   41603
   41609   41611   41617   41621   41627   41641   41647   41651   41659   41669
   41681   41687   41719   41729   41737   41759   41761   41771   41777   41801
   41809   41813   41843   41849   41851   41863   41879   41887   41893   41897
   41903   41911   41927   41941   41947   41953   41957   41959   41969   41981
   41983   41999   42013   42017   42019   42023   42043   42061   42071   42073
   42083   42089   42101   42131   42139   42157   42169   42179   42181   42187
   42193   42197   42209   42221   42223   42227   42239   42257   42281   42283
   42293   42299   42307   42323   42331   42337   42349   42359   42373   42379
   42391   42397   42403   42407   42409   42433   42437   42443   42451   42457
   42461   42463   42467   42473   42487   42491   42499   42509   42533   42557
   42569   42571   42577   42589   42611   42641   42643   42649   42667   42677
   42683   42689   42697   42701   42703   42709   42719   42727   42737   42743
   42751   42767   42773   42787   42793   42797   42821   42829   42839   42841
   42853   42859   42863   42899   42901   42923   42929   42937   42943   42953
   42961   42967   42979   42989   43003   43013   43019   43037   43049   43051
   43063   43067   43093   43103   43117   43133   43151   43159   43177   43189
   43201   43207   43223   43237   43261   43271   43283   43291   43313   43319
   43321   43331   43391   43397   43399   43403   43411   43427   43441   43451
   43457   43481   43487   43499   43517   43541   43543   43573   43577   43579
   43591   43597   43607   43609   43613   43627   43633   43649   43651   43661
   43669   43691   43711   43717   43721   43753   43759   43777   43781   43783
   43787   43789   43793   43801   43853   43867   43889   43891   43913   43933
   43943   43951   43961   43963   43969   43973   43987   43991   43997   44017
   44021   44027   44029   44041   44053   44059   44071   44087   44089   44101
   44111   44119   44123   44129   44131   44159   44171   44179   44189   44201
   44203   44207   44221   44249   44257   44263   44267   44269   44273   44279
   44281   44293   44351   44357   44371   44381   44383   44389   44417   44449
   44453   44483   44491   44497   44501   44507   44519   44531   44533   44537
   44543   44549   44563   44579   44587   44617   44621   44623   44633   44641
   44647   44651   44657   44683   44687   44699   44701   44711   44729   44741
   44753   44771   44773   44777   44789   44797   44809   44819   44839   44843
   44851   44867   44879   44887   44893   44909   44917   44927   44939   44953
   44959   44963   44971   44983   44987   45007   45013   45053   45061   45077
   45083   45119   45121   45127   45131   45137   45139   45161   45179   45181
   45191   45197   45233   45247   45259   45263   45281   45289   45293   45307
   45317   45319   45329   45337   45341   45343   45361   45377   45389   45403
   45413   45427   45433   45439   45481   45491   45497   45503   45523   45533
   45541   45553   45557   45569   45587   45589   45599   45613   45631   45641
   45659   45667   45673   45677   45691   45697   45707   45737   45751   45757
   45763   45767   45779   45817   45821   45823   45827   45833   45841   45853
   45863   45869   45887   45893   45943   45949   45953   45959   45971   45979
   45989   46021   46027   46049   46051   46061   46073   46091   46093   46099
   46103   46133   46141   46147   46153   46171   46181   46183   46187   46199
   46219   46229   46237   46261   46271   46273   46279   46301   46307   46309
   46327   46337   46349   46351   46381   46399   46411   46439   46441   46447
   46451   46457   46471   46477   46489   46499   46507   46511   46523   46549
   46559   46567   46573   46589   46591   46601   46619   46633   46639   46643
   46649   46663   46679   46681   46687   46691   46703   46723   46727   46747
   46751   46757   46769   46771   46807   46811   46817   46819   46829   46831
   46853   46861   46867   46877   46889   46901   46919   46933   46957   46993
   46997   47017   47041   47051   47057   47059   47087   47093   47111   47119
   47123   47129   47137   47143   47147   47149   47161   47189   47207   47221
   47237   47251   47269   47279   47287   47293   47297   47303   47309   47317
   47339   47351   47353   47363   47381   47387   47389   47407   47417   47419
   47431   47441   47459   47491   47497   47501   47507   47513   47521   47527
   47533   47543   47563   47569   47581   47591   47599   47609   47623   47629
   47639   47653   47657   47659   47681   47699   47701   47711   47713   47717
   47737   47741   47743   47777   47779   47791   47797   47807   47809   47819
   47837   47843   47857   47869   47881   47903   47911   47917   47933   47939
   47947   47951   47963   47969   47977   47981   48017   48023   48029   48049
   48073   48079   48091   48109   48119   48121   48131   48157   48163   48179
   48187   48193   48197   48221   48239   48247   48259   48271   48281   48299
   48311   48313   48337   48341   48353   48371   48383   48397   48407   48409
   48413   48437   48449   48463   48473   48479   48481   48487   48491   48497
   48523   48527   48533   48539   48541   48563   48571   48589   48593   48611
   48619   48623   48647   48649   48661   48673   48677   48679   48731   48733
   48751   48757   48761   48767   48779   48781   48787   48799   48809   48817
   48821   48823   48847   48857   48859   48869   48871   48883   48889   48907
   48947   48953   48973   48989   48991   49003   49009   49019   49031   49033
   49037   49043   49057   49069   49081   49103   49109   49117   49121   49123
   49139   49157   49169   49171   49177   49193   49199   49201   49207   49211
   49223   49253   49261   49277   49279   49297   49307   49331   49333   49339
   49363   49367   49369   49391   49393   49409   49411   49417   49429   49433
   49451   49459   49463   49477   49481   49499   49523   49529   49531   49537
   49547   49549   49559   49597   49603   49613   49627   49633   49639   49663
   49667   49669   49681   49697   49711   49727   49739   49741   49747   49757
   49783   49787   49789   49801   49807   49811   49823   49831   49843   49853
   49871   49877   49891   49919   49921   49927   49937   49939   49943   49957
   49991   49993   49999   50021   50023   50033   50047   50051   50053   50069
   50077   50087   50093   50101   50111   50119   50123   50129   50131   50147
   50153   50159   50177   50207   50221   50227   50231   50261   50263   50273
   50287   50291   50311   50321   50329   50333   50341   50359   50363   50377
   50383   50387   50411   50417   50423   50441   50459   50461   50497   50503
   50513   50527   50539   50543   50549   50551   50581   50587   50591   50593
   50599   50627   50647   50651   50671   50683   50707   50723   50741   50753
   50767   50773   50777   50789   50821   50833   50839   50849   50857   50867
   50873   50891   50893   50909   50923   50929   50951   50957   50969   50971
   50989   50993   51001   51031   51043   51047   51059   51061   51071   51109
   51131   51133   51137   51151   51157   51169   51193   51197   51199   51203
   51217   51229   51239   51241   51257   51263   51283   51287   51307   51329
   51341   51343   51347   51349   51361   51383   51407   51413   51419   51421
   51427   51431   51437   51439   51449   51461   51473   51479   51481   51487
   51503   51511   51517   51521   51539   51551   51563   51577   51581   51593
   51599   51607   51613   51631   51637   51647   51659   51673   51679   51683
   51691   51713   51719   51721   51749   51767   51769   51787   51797   51803
   51817   51827   51829   51839   51853   51859   51869   51871   51893   51899
   51907   51913   51929   51941   51949   51971   51973   51977   51991   52009
   52021   52027   52051   52057   52067   52069   52081   52103   52121   52127
   52147   52153   52163   52177   52181   52183   52189   52201   52223   52237
   52249   52253   52259   52267   52289   52291   52301   52313   52321   52361
   52363   52369   52379   52387   52391   52433   52453   52457   52489   52501
   52511   52517   52529   52541   52543   52553   52561   52567   52571   52579
   52583   52609   52627   52631   52639   52667   52673   52691   52697   52709
   52711   52721   52727   52733   52747   52757   52769   52783   52807   52813
   52817   52837   52859   52861   52879   52883   52889   52901   52903   52919
   52937   52951   52957   52963   52967   52973   52981   52999   53003   53017
   53047   53051   53069   53077   53087   53089   53093   53101   53113   53117
   53129   53147   53149   53161   53171   53173   53189   53197   53201   53231
   53233   53239   53267   53269   53279   53281   53299   53309   53323   53327
   53353   53359   53377   53381   53401   53407   53411   53419   53437   53441
   53453   53479   53503   53507   53527   53549   53551   53569   53591   53593
   53597   53609   53611   53617   53623   53629   53633   53639   53653   53657
   53681   53693   53699   53717   53719   53731   53759   53773   53777   53783
   53791   53813   53819   53831   53849   53857   53861   53881   53887   53891
   53897   53899   53917   53923   53927   53939   53951   53959   53987   53993
   54001   54011   54013   54037   54049   54059   54083   54091   54101   54121
   54133   54139   54151   54163   54167   54181   54193   54217   54251   54269
   54277   54287   54293   54311   54319   54323   54331   54347   54361   54367
   54371   54377   54401   54403   54409   54413   54419   54421   54437   54443
   54449   54469   54493   54497   54499   54503   54517   54521   54539   54541
   54547   54559   54563   54577   54581   54583   54601   54617   54623   54629
   54631   54647   54667   54673   54679   54709   54713   54721   54727   54751
   54767   54773   54779   54787   54799   54829   54833   54851   54869   54877
   54881   54907   54917   54919   54941   54949   54959   54973   54979   54983
   55001   55009   55021   55049   55051   55057   55061   55073   55079   55103
   55109   55117   55127   55147   55163   55171   55201   55207   55213   55217
   55219   55229   55243   55249   55259   55291   55313   55331   55333   55337
   55339   55343   55351   55373   55381   55399   55411   55439   55441   55457
   55469   55487   55501   55511   55529   55541   55547   55579   55589   55603
   55609   55619   55621   55631   55633   55639   55661   55663   55667   55673
   55681   55691   55697   55711   55717   55721   55733   55763   55787   55793
   55799   55807   55813   55817   55819   55823   55829   55837   55843   55849
   55871   55889   55897   55901   55903   55921   55927   55931   55933   55949
   55967   55987   55997   56003   56009   56039   56041   56053   56081   56087
   56093   56099   56101   56113   56123   56131   56149   56167   56171   56179
   56197   56207   56209   56237   56239   56249   56263   56267   56269   56299
   56311   56333   56359   56369   56377   56383   56393   56401   56417   56431
   56437   56443   56453   56467   56473   56477   56479   56489   56501   56503
   56509   56519   56527   56531   56533   56543   56569   56591   56597   56599
   56611   56629   56633   56659   56663   56671   56681   56687   56701   56711
   56713   56731   56737   56747   56767   56773   56779   56783   56807   56809
   56813   56821   56827   56843   56857   56873   56891   56893   56897   56909
   56911   56921   56923   56929   56941   56951   56957   56963   56983   56989
   56993   56999   57037   57041   57047   57059   57073   57077   57089   57097
   57107   57119   57131   57139   57143   57149   57163   57173   57179   57191
   57193   57203   57221   57223   57241   57251   57259   57269   57271   57283
   57287   57301   57329   57331   57347   57349   57367   57373   57383   57389
   57397   57413   57427   57457   57467   57487   57493   57503   57527   57529
   57557   57559   57571   57587   57593   57601   57637   57641   57649   57653
   57667   57679   57689   57697   57709   57713   57719   57727   57731   57737
   57751   57773   57781   57787   57791   57793   57803   57809   57829   57839
   57847   57853   57859   57881   57899   57901   57917   57923   57943   57947
   57973   57977   57991   58013   58027   58031   58043   58049   58057   58061
   58067   58073   58099   58109   58111   58129   58147   58151   58153   58169
   58171   58189   58193   58199   58207   58211   58217   58229   58231   58237
   58243   58271   58309   58313   58321   58337   58363   58367   58369   58379
   58391   58393   58403   58411   58417   58427   58439   58441   58451   58453
   58477   58481   58511   58537   58543   58549   58567   58573   58579   58601
   58603   58613   58631   58657   58661   58679   58687   58693   58699   58711
   58727   58733   58741   58757   58763   58771   58787   58789   58831   58889
   58897   58901   58907   58909   58913   58921   58937   58943   58963   58967
   58979   58991   58997   59009   59011   59021   59023   59029   59051   59053
   59063   59069   59077   59083   59093   59107   59113   59119   59123   59141
   59149   59159   59167   59183   59197   59207   59209   59219   59221   59233
   59239   59243   59263   59273   59281   59333   59341   59351   59357   59359
   59369   59377   59387   59393   59399   59407   59417   59419   59441   59443
   59447   59453   59467   59471   59473   59497   59509   59513   59539   59557
   59561   59567   59581   59611   59617   59621   59627   59629   59651   59659
   59663   59669   59671   59693   59699   59707   59723   59729   59743   59747
   59753   59771   59779   59791   59797   59809   59833   59863   59879   59887
   59921   59929   59951   59957   59971   59981   59999   60013   60017   60029
   60037   60041   60077   60083   60089   60091   60101   60103   60107   60127
   60133   60139   60149   60161   60167   60169   60209   60217   60223   60251
   60257   60259   60271   60289   60293   60317   60331   60337   60343   60353
   60373   60383   60397   60413   60427   60443   60449   60457   60493   60497
   60509   60521   60527   60539   60589   60601   60607   60611   60617   60623
   60631   60637   60647   60649   60659   60661   60679   60689   60703   60719
   60727   60733   60737   60757   60761   60763   60773   60779   60793   60811
   60821   60859   60869   60887   60889   60899   60901   60913   60917   60919
   60923   60937   60943   60953   60961   61001   61007   61027   61031   61043
   61051   61057   61091   61099   61121   61129   61141   61151   61153   61169
   61211   61223   61231   61253   61261   61283   61291   61297   61331   61333
   61339   61343   61357   61363   61379   61381   61403   61409   61417   61441
   61463   61469   61471   61483   61487   61493   61507   61511   61519   61543
   61547   61553   61559   61561   61583   61603   61609   61613   61627   61631
   61637   61643   61651   61657   61667   61673   61681   61687   61703   61717
   61723   61729   61751   61757   61781   61813   61819   61837   61843   61861
   61871   61879   61909   61927   61933   61949   61961   61967   61979   61981
   61987   61991   62003   62011   62017   62039   62047   62053   62057   62071
   62081   62099   62119   62129   62131   62137   62141   62143   62171   62189
   62191   62201   62207   62213   62219   62233   62273   62297   62299   62303
   62311   62323   62327   62347   62351   62383   62401   62417   62423   62459
   62467   62473   62477   62483   62497   62501   62507   62533   62539   62549
   62563   62581   62591   62597   62603   62617   62627   62633   62639   62653
   62659   62683   62687   62701   62723   62731   62743   62753   62761   62773
   62791   62801   62819   62827   62851   62861   62869   62873   62897   62903
   62921   62927   62929   62939   62969   62971   62981   62983   62987   62989
   63029   63031   63059   63067   63073   63079   63097   63103   63113   63127
   63131   63149   63179   63197   63199   63211   63241   63247   63277   63281
   63299   63311   63313   63317   63331   63337   63347   63353   63361   63367
   63377   63389   63391   63397   63409   63419   63421   63439   63443   63463
   63467   63473   63487   63493   63499   63521   63527   63533   63541   63559
   63577   63587   63589   63599   63601   63607   63611   63617   63629   63647
   63649   63659   63667   63671   63689   63691   63697   63703   63709   63719
   63727   63737   63743   63761   63773   63781   63793   63799   63803   63809
   63823   63839   63841   63853   63857   63863   63901   63907   63913   63929
   63949   63977   63997   64007   64013   64019   64033   64037   64063   64067
   64081   64091   64109   64123   64151   64153   64157   64171   64187   64189
   64217   64223   64231   64237   64271   64279   64283   64301   64303   64319
   64327   64333   64373   64381   64399   64403   64433   64439   64451   64453
   64483   64489   64499   64513   64553   64567   64577   64579   64591   64601
   64609   64613   64621   64627   64633   64661   64663   64667   64679   64693
   64709   64717   64747   64763   64781   64783   64793   64811   64817   64849
   64853   64871   64877   64879   64891   64901   64919   64921   64927   64937
   64951   64969   64997   65003   65011   65027   65029   65033   65053   65063
   65071   65089   65099   65101   65111   65119   65123   65129   65141   65147
   65167   65171   65173   65179   65183   65203   65213   65239   65257   65267
   65269   65287   65293   65309   65323   65327   65353   65357   65371   65381
   65393   65407   65413   65419   65423   65437   65447   65449   65479   65497
   65519   65521   65537   65539   65543   65551   65557   65563   65579   65581
   65587   65599   65609   65617   65629   65633   65647   65651   65657   65677
   65687   65699   65701   65707   65713   65717   65719   65729   65731   65761
   65777   65789   65809   65827   65831   65837   65839   65843   65851   65867
   65881   65899   65921   65927   65929   65951   65957   65963   65981   65983
   65993   66029   66037   66041   66047   66067   66071   66083   66089   66103
   66107   66109   66137   66161   66169   66173   66179   66191   66221   66239
   66271   66293   66301   66337   66343   66347   66359   66361   66373   66377
   66383   66403   66413   66431   66449   66457   66463   66467   66491   66499
   66509   66523   66529   66533   66541   66553   66569   66571   66587   66593
   66601   66617   66629   66643   66653   66683   66697   66701   66713   66721
   66733   66739   66749   66751   66763   66791   66797   66809   66821   66841
   66851   66853   66863   66877   66883   66889   66919   66923   66931   66943
   66947   66949   66959   66973   66977   67003   67021   67033   67043   67049
   67057   67061   67073   67079   67103   67121   67129   67139   67141   67153
   67157   67169   67181   67187   67189   67211   67213   67217   67219   67231
   67247   67261   67271   67273   67289   67307   67339   67343   67349   67369
   67391   67399   67409   67411   67421   67427   67429   67433   67447   67453
   67477   67481   67489   67493   67499   67511   67523   67531   67537   67547
   67559   67567   67577   67579   67589   67601   67607   67619   67631   67651
   67679   67699   67709   67723   67733   67741   67751   67757   67759   67763
   67777   67783   67789   67801   67807   67819   67829   67843   67853   67867
   67883   67891   67901   67927   67931   67933   67939   67943   67957   67961
   67967   67979   67987   67993   68023   68041   68053   68059   68071   68087
   68099   68111   68113   68141   68147   68161   68171   68207   68209   68213
   68219   68227   68239   68261   68279   68281   68311   68329   68351   68371
   68389   68399   68437   68443   68447   68449   68473   68477   68483   68489
   68491   68501   68507   68521   68531   68539   68543   68567   68581   68597
   68611   68633   68639   68659   68669   68683   68687   68699   68711   68713
   68729   68737   68743   68749   68767   68771   68777   68791   68813   68819
   68821   68863   68879   68881   68891   68897   68899   68903   68909   68917
   68927   68947   68963   68993   69001   69011   69019   69029   69031   69061
   69067   69073   69109   69119   69127   69143   69149   69151   69163   69191
   69193   69197   69203   69221   69233   69239   69247   69257   69259   69263
   69313   69317   69337   69341   69371   69379   69383   69389   69401   69403
   69427   69431   69439   69457   69463   69467   69473   69481   69491   69493
   69497   69499   69539   69557   69593   69623   69653   69661   69677   69691
   69697   69709   69737   69739   69761   69763   69767   69779   69809   69821
   69827   69829   69833   69847   69857   69859   69877   69899   69911   69929
   69931   69941   69959   69991   69997   70001   70003   70009   70019   70039
   70051   70061   70067   70079   70099   70111   70117   70121   70123   70139
   70141   70157   70163   70177   70181   70183   70199   70201   70207   70223
   70229   70237   70241   70249   70271   70289   70297   70309   70313   70321
   70327   70351   70373   70379   70381   70393   70423   70429   70439   70451
   70457   70459   70481   70487   70489   70501   70507   70529   70537   70549
   70571   70573   70583   70589   70607   70619   70621   70627   70639   70657
   70663   70667   70687   70709   70717   70729   70753   70769   70783   70793
   70823   70841   70843   70849   70853   70867   70877   70879   70891   70901
   70913   70919   70921   70937   70949   70951   70957   70969   70979   70981
   70991   70997   70999   71011   71023   71039   71059   71069   71081   71089
   71119   71129   71143   71147   71153   71161   71167   71171   71191   71209
   71233   71237   71249   71257   71261   71263   71287   71293   71317   71327
   71329   71333   71339   71341   71347   71353   71359   71363   71387   71389
   71399   71411   71413   71419   71429   71437   71443   71453   71471   71473
   71479   71483   71503   71527   71537   71549   71551   71563   71569   71593
   71597   71633   71647   71663   71671   71693   71699   71707   71711   71713
   71719   71741   71761   71777   71789   71807   71809   71821   71837   71843
   71849   71861   71867   71879   71881   71887   71899   71909   71917   71933
   71941   71947   71963   71971   71983   71987   71993   71999   72019   72031
   72043   72047   72053   72073   72077   72089   72091   72101   72103   72109
   72139   72161   72167   72169   72173   72211   72221   72223   72227   72229
   72251   72253   72269   72271   72277   72287   72307   72313   72337   72341
   72353   72367   72379   72383   72421   72431   72461   72467   72469   72481
   72493   72497   72503   72533   72547   72551   72559   72577   72613   72617
   72623   72643   72647   72649   72661   72671   72673   72679   72689   72701
   72707   72719   72727   72733   72739   72763   72767   72797   72817   72823
   72859   72869   72871   72883   72889   72893   72901   72907   72911   72923
   72931   72937   72949   72953   72959   72973   72977   72997   73009   73013
   73019   73037   73039   73043   73061   73063   73079   73091   73121   73127
   73133   73141   73181   73189   73237   73243   73259   73277   73291   73303
   73309   73327   73331   73351   73361   73363   73369   73379   73387   73417
   73421   73433   73453   73459   73471   73477   73483   73517   73523   73529
   73547   73553   73561   73571   73583   73589   73597   73607   73609   73613
   73637   73643   73651   73673   73679   73681   73693   73699   73709   73721
   73727   73751   73757   73771   73783   73819   73823   73847   73849   73859
   73867   73877   73883   73897   73907   73939   73943   73951   73961   73973
   73999   74017   74021   74027   74047   74051   74071   74077   74093   74099
   74101   74131   74143   74149   74159   74161   74167   74177   74189   74197
   74201   74203   74209   74219   74231   74257   74279   74287   74293   74297
   74311   74317   74323   74353   74357   74363   74377   74381   74383   74411
   74413   74419   74441   74449   74453   74471   74489   74507   74509   74521
   74527   74531   74551   74561   74567   74573   74587   74597   74609   74611
   74623   74653   74687   74699   74707   74713   74717   74719   74729   74731
   74747   74759   74761   74771   74779   74797   74821   74827   74831   74843
   74857   74861   74869   74873   74887   74891   74897   74903   74923   74929
   74933   74941   74959   75011   75013   75017   75029   75037   75041   75079
   75083   75109   75133   75149   75161   75167   75169   75181   75193   75209
   75211   75217   75223   75227   75239   75253   75269   75277   75289   75307
   75323   75329   75337   75347   75353   75367   75377   75389   75391   75401
   75403   75407   75431   75437   75479   75503   75511   75521   75527   75533
   75539   75541   75553   75557   75571   75577   75583   75611   75617   75619
   75629   75641   75653   75659   75679   75683   75689   75703   75707   75709
   75721   75731   75743   75767   75773   75781   75787   75793   75797   75821
   75833   75853   75869   75883   75913   75931   75937   75941   75967   75979
   75983   75989   75991   75997   76001   76003   76031   76039   76079   76081
   76091   76099   76103   76123   76129   76147   76157   76159   76163   76207
   76213   76231   76243   76249   76253   76259   76261   76283   76289   76303
   76333   76343   76367   76369   76379   76387   76403   76421   76423   76441
   76463   76471   76481   76487   76493   76507   76511   76519   76537   76541
   76543   76561   76579   76597   76603   76607   76631   76649   76651   76667
   76673   76679   76697   76717   76733   76753   76757   76771   76777   76781
   76801   76819   76829   76831   76837   76847   76871   76873   76883   76907
   76913   76919   76943   76949   76961   76963   76991   77003   77017   77023
   77029   77041   77047   77069   77081   77093   77101   77137   77141   77153
   77167   77171   77191   77201   77213   77237   77239   77243   77249   77261
   77263   77267   77269   77279   77291   77317   77323   77339   77347   77351
   77359   77369   77377   77383   77417   77419   77431   77447   77471   77477
   77479   77489   77491   77509   77513   77521   77527   77543   77549   77551
   77557   77563   77569   77573   77587   77591   77611   77617   77621   77641
   77647   77659   77681   77687   77689   77699   77711   77713   77719   77723
   77731   77743   77747   77761   77773   77783   77797   77801   77813   77839
   77849   77863   77867   77893   77899   77929   77933   77951   77969   77977
   77983   77999   78007   78017   78031   78041   78049   78059   78079   78101
   78121   78137   78139   78157   78163   78167   78173   78179   78191   78193
   78203   78229   78233   78241   78259   78277   78283   78301   78307   78311
   78317   78341   78347   78367   78401   78427   78437   78439   78467   78479
   78487   78497   78509   78511   78517   78539   78541   78553   78569   78571
   78577   78583   78593   78607   78623   78643   78649   78653   78691   78697
   78707   78713   78721   78737   78779   78781   78787   78791   78797   78803
   78809   78823   78839   78853   78857   78877   78887   78889   78893   78901
   78919   78929   78941   78977   78979   78989   79031   79039   79043   79063
   79087   79103   79111   79133   79139   79147   79151   79153   79159   79181
   79187   79193   79201   79229   79231   79241   79259   79273   79279   79283
   79301   79309   79319   79333   79337   79349   79357   79367   79379   79393
   79397   79399   79411   79423   79427   79433   79451   79481   79493   79531
   79537   79549   79559   79561   79579   79589   79601   79609   79613   79621
   79627   79631   79633   79657   79669   79687   79691   79693   79697   79699
   79757   79769   79777   79801   79811   79813   79817   79823   79829   79841
   79843   79847   79861   79867   79873   79889   79901   79903   79907   79939
   79943   79967   79973   79979   79987   79997   79999   80021   80039   80051
   80071   80077   80107   80111   80141   80147   80149   80153   80167   80173
   80177   80191   80207   80209   80221   80231   80233   80239   80251   80263
   80273   80279   80287   80309   80317   80329   80341   80347   80363   80369
   80387   80407   80429   80447   80449   80471   80473   80489   80491   80513
   80527   80537   80557   80567   80599   80603   80611   80621   80627   80629
   80651   80657   80669   80671   80677   80681   80683   80687   80701   80713
   80737   80747   80749   80761   80777   80779   80783   80789   80803   80809
   80819   80831   80833   80849   80863   80897   80909   80911   80917   80923
   80929   80933   80953   80963   80989   81001   81013   81017   81019   81023
   81031   81041   81043   81047   81049   81071   81077   81083   81097   81101
   81119   81131   81157   81163   81173   81181   81197   81199   81203   81223
   81233   81239   81281   81283   81293   81299   81307   81331   81343   81349
   81353   81359   81371   81373   81401   81409   81421   81439   81457   81463
   81509   81517   81527   81533   81547   81551   81553   81559   81563   81569
   81611   81619   81629   81637   81647   81649   81667   81671   81677   81689
   81701   81703   81707   81727   81737   81749   81761   81769   81773   81799
   81817   81839   81847   81853   81869   81883   81899   81901   81919   81929
   81931   81937   81943   81953   81967   81971   81973   82003   82007   82009
   82013   82021   82031   82037   82039   82051   82067   82073   82129   82139
   82141   82153   82163   82171   82183   82189   82193   82207   82217   82219
   82223   82231   82237   82241   82261   82267   82279   82301   82307   82339
   82349   82351   82361   82373   82387   82393   82421   82457   82463   82469
   82471   82483   82487   82493   82499   82507   82529   82531   82549   82559
   82561   82567   82571   82591   82601   82609   82613   82619   82633   82651
   82657   82699   82721   82723   82727   82729   82757   82759   82763   82781
   82787   82793   82799   82811   82813   82837   82847   82883   82889   82891
   82903   82913   82939   82963   82981   82997   83003   83009   83023   83047
   83059   83063   83071   83077   83089   83093   83101   83117   83137   83177
   83203   83207   83219   83221   83227   83231   83233   83243   83257   83267
   83269   83273   83299   83311   83339   83341   83357   83383   83389   83399
   83401   83407   83417   83423   83431   83437   83443   83449   83459   83471
   83477   83497   83537   83557   83561   83563   83579   83591   83597   83609
   83617   83621   83639   83641   83653   83663   83689   83701   83717   83719
   83737   83761   83773   83777   83791   83813   83833   83843   83857   83869
   83873   83891   83903   83911   83921   83933   83939   83969   83983   83987
   84011   84017   84047   84053   84059   84061   84067   84089   84121   84127
   84131   84137   84143   84163   84179   84181   84191   84199   84211   84221
   84223   84229   84239   84247   84263   84299   84307   84313   84317   84319
   84347   84349   84377   84389   84391   84401   84407   84421   84431   84437
   84443   84449   84457   84463   84467   84481   84499   84503   84509   84521
   84523   84533   84551   84559   84589   84629   84631   84649   84653   84659
   84673   84691   84697   84701   84713   84719   84731   84737   84751   84761
   84787   84793   84809   84811   84827   84857   84859   84869   84871   84913
   84919   84947   84961   84967   84977   84979   84991   85009   85021   85027
   85037   85049   85061   85081   85087   85091   85093   85103   85109   85121
   85133   85147   85159   85193   85199   85201   85213   85223   85229   85237
   85243   85247   85259   85297   85303   85313   85331   85333   85361   85363
   85369   85381   85411   85427   85429   85439   85447   85451   85453   85469
   85487   85513   85517   85523   85531   85549   85571   85577   85597   85601
   85607   85619   85621   85627   85639   85643   85661   85667   85669   85691
   85703   85711   85717   85733   85751   85781   85793   85817   85819   85829
   85831   85837   85843   85847   85853   85889   85903   85909   85931   85933
   85991   85999   86011   86017   86027   86029   86069   86077   86083   86111
   86113   86117   86131   86137   86143   86161   86171   86179   86183   86197
   86201   86209   86239   86243   86249   86257   86263   86269   86287   86291
   86293   86297   86311   86323   86341   86351   86353   86357   86369   86371
   86381   86389   86399   86413   86423   86441   86453   86461   86467   86477
   86491   86501   86509   86531   86533   86539   86561   86573   86579   86587
   86599   86627   86629   86677   86689   86693   86711   86719   86729   86743
   86753   86767   86771   86783   86813   86837   86843   86851   86857   86861
   86869   86923   86927   86929   86939   86951   86959   86969   86981   86993
   87011   87013   87037   87041   87049   87071   87083   87103   87107   87119
   87121   87133   87149   87151   87179   87181   87187   87211   87221   87223
   87251   87253   87257   87277   87281   87293   87299   87313   87317   87323
   87337   87359   87383   87403   87407   87421   87427   87433   87443   87473
   87481   87491   87509   87511   87517   87523   87539   87541   87547   87553
   87557   87559   87583   87587   87589   87613   87623   87629   87631   87641
   87643   87649   87671   87679   87683   87691   87697   87701   87719   87721
   87739   87743   87751   87767   87793   87797   87803   87811   87833   87853
   87869   87877   87881   87887   87911   87917   87931   87943   87959   87961
   87973   87977   87991   88001   88003   88007   88019   88037   88069   88079
   88093   88117   88129   88169   88177   88211   88223   88237   88241   88259
   88261   88289   88301   88321   88327   88337   88339   88379   88397   88411
   88423   88427   88463   88469   88471   88493   88499   88513   88523   88547
   88589   88591   88607   88609   88643   88651   88657   88661   88663   88667
   88681   88721   88729   88741   88747   88771   88789   88793   88799   88801
   88807   88811   88813   88817   88819   88843   88853   88861   88867   88873
   88883   88897   88903   88919   88937   88951   88969   88993   88997   89003
   89009   89017   89021   89041   89051   89057   89069   89071   89083   89087
   89101   89107   89113   89119   89123   89137   89153   89189   89203   89209
   89213   89227   89231   89237   89261   89269   89273   89293   89303   89317
   89329   89363   89371   89381   89387   89393   89399   89413   89417   89431
   89443   89449   89459   89477   89491   89501   89513   89519   89521   89527
   89533   89561   89563   89567   89591   89597   89599   89603   89611   89627
   89633   89653   89657   89659   89669   89671   89681   89689   89753   89759
   89767   89779   89783   89797   89809   89819   89821   89833   89839   89849
   89867   89891   89897   89899   89909   89917   89923   89939   89959   89963
   89977   89983   89989   90001   90007   90011   90017   90019   90023   90031
   90053   90059   90067   90071   90073   90089   90107   90121   90127   90149
   90163   90173   90187   90191   90197   90199   90203   90217   90227   90239
   90247   90263   90271   90281   90289   90313   90353   90359   90371   90373
   90379   90397   90401   90403   90407   90437   90439   90469   90473   90481
   90499   90511   90523   90527   90529   90533   90547   90583   90599   90617
   90619   90631   90641   90647   90659   90677   90679   90697   90703   90709
   90731   90749   90787   90793   90803   90821   90823   90833   90841   90847
   90863   90887   90901   90907   90911   90917   90931   90947   90971   90977
   90989   90997   91009   91019   91033   91079   91081   91097   91099   91121
   91127   91129   91139   91141   91151   91153   91159   91163   91183   91193
   91199   91229   91237   91243   91249   91253   91283   91291   91297   91303
   91309   91331   91367   91369   91373   91381   91387   91393   91397   91411
   91423   91433   91453   91457   91459   91463   91493   91499   91513   91529
   91541   91571   91573   91577   91583   91591   91621   91631   91639   91673
   91691   91703   91711   91733   91753   91757   91771   91781   91801   91807
   91811   91813   91823   91837   91841   91867   91873   91909   91921   91939
   91943   91951   91957   91961   91967   91969   91997   92003   92009   92033
   92041   92051   92077   92083   92107   92111   92119   92143   92153   92173
   92177   92179   92189   92203   92219   92221   92227   92233   92237   92243
   92251   92269   92297   92311   92317   92333   92347   92353   92357   92363
   92369   92377   92381   92383   92387   92399   92401   92413   92419   92431
   92459   92461   92467   92479   92489   92503   92507   92551   92557   92567
   92569   92581   92593   92623   92627   92639   92641   92647   92657   92669
   92671   92681   92683   92693   92699   92707   92717   92723   92737   92753
   92761   92767   92779   92789   92791   92801   92809   92821   92831   92849
   92857   92861   92863   92867   92893   92899   92921   92927   92941   92951
   92957   92959   92987   92993   93001   93047   93053   93059   93077   93083
   93089   93097   93103   93113   93131   93133   93139   93151   93169   93179
   93187   93199   93229   93239   93241   93251   93253   93257   93263   93281
   93283   93287   93307   93319   93323   93329   93337   93371   93377   93383
   93407   93419   93427   93463   93479   93481   93487   93491   93493   93497
   93503   93523   93529   93553   93557   93559   93563   93581   93601   93607
   93629   93637   93683   93701   93703   93719   93739   93761   93763   93787
   93809   93811   93827   93851   93871   93887   93889   93893   93901   93911
   93913   93923   93937   93941   93949   93967   93971   93979   93983   93997
   94007   94009   94033   94049   94057   94063   94079   94099   94109   94111
   94117   94121   94151   94153   94169   94201   94207   94219   94229   94253
   94261   94273   94291   94307   94309   94321   94327   94331   94343   94349
   94351   94379   94397   94399   94421   94427   94433   94439   94441   94447
   94463   94477   94483   94513   94529   94531   94541   94543   94547   94559
   94561   94573   94583   94597   94603   94613   94621   94649   94651   94687
   94693   94709   94723   94727   94747   94771   94777   94781   94789   94793
   94811   94819   94823   94837   94841   94847   94849   94873   94889   94903
   94907   94933   94949   94951   94961   94993   94999   95003   95009   95021
   95027   95063   95071   95083   95087   95089   95093   95101   95107   95111
   95131   95143   95153   95177   95189   95191   95203   95213   95219   95231
   95233   95239   95257   95261   95267   95273   95279   95287   95311   95317
   95327   95339   95369   95383   95393   95401   95413   95419   95429   95441
   95443   95461   95467   95471   95479   95483   95507   95527   95531   95539
   95549   95561   95569   95581   95597   95603   95617   95621   95629   95633
   95651   95701   95707   95713   95717   95723   95731   95737   95747   95773
   95783   95789   95791   95801   95803   95813   95819   95857   95869   95873
   95881   95891   95911   95917   95923   95929   95947   95957   95959   95971
   95987   95989   96001   96013   96017   96043   96053   96059   96079   96097
   96137   96149   96157   96167   96179   96181   96199   96211   96221   96223
   96233   96259   96263   96269   96281   96289   96293   96323   96329   96331
   96337   96353   96377   96401   96419   96431   96443   96451   96457   96461
   96469   96479   96487   96493   96497   96517   96527   96553   96557   96581
   96587   96589   96601   96643   96661   96667   96671   96697   96703   96731
   96737   96739   96749   96757   96763   96769   96779   96787   96797   96799
   96821   96823   96827   96847   96851   96857   96893   96907   96911   96931
   96953   96959   96973   96979   96989   96997   97001   97003   97007   97021
   97039   97073   97081   97103   97117   97127   97151   97157   97159   97169
   97171   97177   97187   97213   97231   97241   97259   97283   97301   97303
   97327   97367   97369   97373   97379   97381   97387   97397   97423   97429
   97441   97453   97459   97463   97499   97501   97511   97523   97547   97549
   97553   97561   97571   97577   97579   97583   97607   97609   97613   97649
   97651   97673   97687   97711   97729   97771   97777   97787   97789   97813
   97829   97841   97843   97847   97849   97859   97861   97871   97879   97883
   97919   97927   97931   97943   97961   97967   97973   97987   98009   98011
   98017   98041   98047   98057   98081   98101   98123   98129   98143   98179
   98207   98213   98221   98227   98251   98257   98269   98297   98299   98317
   98321   98323   98327   98347   98369   98377   98387   98389   98407   98411
   98419   98429   98443   98453   98459   98467   98473   98479   98491   98507
   98519   98533   98543   98561   98563   98573   98597   98621   98627   98639
   98641   98663   98669   98689   98711   98713   98717   98729   98731   98737
   98773   98779   98801   98807   98809   98837   98849   98867   98869   98873
   98887   98893   98897   98899   98909   98911   98927   98929   98939   98947
   98953   98963   98981   98993   98999   99013   99017   99023   99041   99053
   99079   99083   99089   99103   99109   99119   99131   99133   99137   99139
   99149   99173   99181   99191   99223   99233   99241   99251   99257   99259
   99277   99289   99317   99347   99349   99367   99371   99377   99391   99397
   99401   99409   99431   99439   99469   99487   99497   99523   99527   99529
   99551   99559   99563   99571   99577   99581   99607   99611   99623   99643
   99661   99667   99679   99689   99707   99709   99713   99719   99721   99733
   99761   99767   99787   99793   99809   99817   99823   99829   99833   99839
   99859   99871   99877   99881   99901   99907   99923   99929   99961   99971
   99989   99991  100003  100019  100043  100049  100057  100069  100103  100109
  100129  100151  100153  100169  100183  100189  100193  100207  100213  100237
  100267  100271  100279  100291  100297  100313  100333  100343  100357  100361
  100363  100379  100391  100393  100403  100411  100417  100447  100459  100469
  100483  100493  100501  100511  100517  100519  100523  100537  100547  100549
  100559  100591  100609  100613  100621  100649  100669  100673  100693  100699
  100703  100733  100741  100747  100769  100787  100799  100801  100811  100823
  100829  100847  100853  100907  100913  100927  100931  100937  100943  100957
  100981  100987  100999  101009  101021  101027  101051  101063  101081  101089
  101107  101111  101113  101117  101119  101141  101149  101159  101161  101173
  101183  101197  101203  101207  101209  101221  101267  101273  101279  101281
  101287  101293  101323  101333  101341  101347  101359  101363  101377  101383
  101399  101411  101419  101429  101449  101467  101477  101483  101489  101501
  101503  101513  101527  101531  101533  101537  101561  101573  101581  101599
  101603  101611  101627  101641  101653  101663  101681  101693  101701  101719
  101723  101737  101741  101747  101749  101771  101789  101797  101807  101833
  101837  101839  101863  101869  101873  101879  101891  101917  101921  101929
  101939  101957  101963  101977  101987  101999  102001  102013  102019  102023
  102031  102043  102059  102061  102071  102077  102079  102101  102103  102107
  102121  102139  102149  102161  102181  102191  102197  102199  102203  102217
  102229  102233  102241  102251  102253  102259  102293  102299  102301  102317
  102329  102337  102359  102367  102397  102407  102409  102433  102437  102451
  102461  102481  102497  102499  102503  102523  102533  102539  102547  102551
  102559  102563  102587  102593  102607  102611  102643  102647  102653  102667
  102673  102677  102679  102701  102761  102763  102769  102793  102797  102811
  102829  102841  102859  102871  102877  102881  102911  102913  102929  102931
  102953  102967  102983  103001  103007  103043  103049  103067  103069  103079
  103087  103091  103093  103099  103123  103141  103171  103177  103183  103217
  103231  103237  103289  103291  103307  103319  103333  103349  103357  103387
  103391  103393  103399  103409  103421  103423  103451  103457  103471  103483
  103511  103529  103549  103553  103561  103567  103573  103577  103583  103591
  103613  103619  103643  103651  103657  103669  103681  103687  103699  103703
  103723  103769  103787  103801  103811  103813  103837  103841  103843  103867
  103889  103903  103913  103919  103951  103963  103967  103969  103979  103981
  103991  103993  103997  104003  104009  104021  104033  104047  104053  104059
  104087  104089  104107  104113  104119  104123  104147  104149  104161  104173
  104179  104183  104207  104231  104233  104239  104243  104281  104287  104297
  104309  104311  104323  104327  104347  104369  104381  104383  104393  104399
  104417  104459  104471  104473  104479  104491  104513  104527  104537  104543
  104549  104551  104561  104579  104593  104597  104623  104639  104651  104659
  104677  104681  104683  104693  104701  104707  104711  104717  104723  104729
  104743  104759  104761  104773  104779  104789  104801  104803  104827  104831
  104849  104851  104869  104879  104891  104911  104917  104933  104947  104953
  104959  104971  104987  104999  105019  105023  105031  105037  105071  105097
  105107  105137  105143  105167  105173  105199  105211  105227  105229  105239
  105251  105253  105263  105269  105277  105319  105323  105331  105337  105341
  105359  105361  105367  105373  105379  105389  105397  105401  105407  105437
  105449  105467  105491  105499  105503  105509  105517  105527  105529  105533
  105541  105557  105563  105601  105607  105613  105619  105649  105653  105667
  105673  105683  105691  105701  105727  105733  105751  105761  105767  105769
  105817  105829  105863  105871  105883  105899  105907  105913  105929  105943
  105953  105967  105971  105977  105983  105997  106013  106019  106031  106033
  106087  106103  106109  106121  106123  106129  106163  106181  106187  106189
  106207  106213  106217  106219  106243  106261  106273  106277  106279  106291
  106297  106303  106307  106319  106321  106331  106349  106357  106363  106367
  106373  106391  106397  106411  106417  106427  106433  106441  106451  106453
  106487  106501  106531  106537  106541  106543  106591  106619  106621  106627
  106637  106649  106657  106661  106663  106669  106681  106693  106699  106703
  106721  106727  106739  106747  106751  106753  106759  106781  106783  106787
  106801  106823  106853  106859  106861  106867  106871  106877  106903  106907
  106921  106937  106949  106957  106961  106963  106979  106993  107021  107033
  107053  107057  107069  107071  107077  107089  107099  107101  107119  107123
  107137  107171  107183  107197  107201  107209  107227  107243  107251  107269
  107273  107279  107309  107323  107339  107347  107351  107357  107377  107441
  107449  107453  107467  107473  107507  107509  107563  107581  107599  107603
  107609  107621  107641  107647  107671  107687  107693  107699  107713  107717
  107719  107741  107747  107761  107773  107777  107791  107827  107837  107839
  107843  107857  107867  107873  107881  107897  107903  107923  107927  107941
  107951  107971  107981  107999  108007  108011  108013  108023  108037  108041
  108061  108079  108089  108107  108109  108127  108131  108139  108161  108179
  108187  108191  108193  108203  108211  108217  108223  108233  108247  108263
  108271  108287  108289  108293  108301  108343  108347  108359  108377  108379
  108401  108413  108421  108439  108457  108461  108463  108497  108499  108503
  108517  108529  108533  108541  108553  108557  108571  108587  108631  108637
  108643  108649  108677  108707  108709  108727  108739  108751  108761  108769
  108791  108793  108799  108803  108821  108827  108863  108869  108877  108881
  108883  108887  108893  108907  108917  108923  108929  108943  108947  108949
  108959  108961  108967  108971  108991  109001  109013  109037  109049  109063
  109073  109097  109103  109111  109121  109133  109139  109141  109147  109159
  109169  109171  109199  109201  109211  109229  109253  109267  109279  109297
  109303  109313  109321  109331  109357  109363  109367  109379  109387  109391
  109397  109423  109433  109441  109451  109453  109469  109471  109481  109507
  109517  109519  109537  109541  109547  109567  109579  109583  109589  109597
  109609  109619  109621  109639  109661  109663  109673  109717  109721  109741
  109751  109789  109793  109807  109819  109829  109831  109841  109843  109847
  109849  109859  109873  109883  109891  109897  109903  109913  109919  109937
  109943  109961  109987  110017  110023  110039  110051  110059  110063  110069
  110083  110119  110129  110161  110183  110221  110233  110237  110251  110261
  110269  110273  110281  110291  110311  110321  110323  110339  110359  110419
  110431  110437  110441  110459  110477  110479  110491  110501  110503  110527
  110533  110543  110557  110563  110567  110569  110573  110581  110587  110597
  110603  110609  110623  110629  110641  110647  110651  110681  110711  110729
  110731  110749  110753  110771  110777  110807  110813  110819  110821  110849
  110863  110879  110881  110899  110909  110917  110921  110923  110927  110933
  110939  110947  110951  110969  110977  110989  111029  111031  111043  111049
  111053  111091  111103  111109  111119  111121  111127  111143  111149  111187
  111191  111211  111217  111227  111229  111253  111263  111269  111271  111301
  111317  111323  111337  111341  111347  111373  111409  111427  111431  111439
  111443  111467  111487  111491  111493  111497  111509  111521  111533  111539
  111577  111581  111593  111599  111611  111623  111637  111641  111653  111659
  111667  111697  111721  111731  111733  111751  111767  111773  111779  111781
  111791  111799  111821  111827  111829  111833  111847  111857  111863  111869
  111871  111893  111913  111919  111949  111953  111959  111973  111977  111997
  112019  112031  112061  112067  112069  112087  112097  112103  112111  112121
  112129  112139  112153  112163  112181  112199  112207  112213  112223  112237
  112241  112247  112249  112253  112261  112279  112289  112291  112297  112303
  112327  112331  112337  112339  112349  112361  112363  112397  112403  112429
  112459  112481  112501  112507  112543  112559  112571  112573  112577  112583
  112589  112601  112603  112621  112643  112657  112663  112687  112691  112741
  112757  112759  112771  112787  112799  112807  112831  112843  112859  112877
  112901  112909  112913  112919  112921  112927  112939  112951  112967  112979
  112997  113011  113017  113021  113023  113027  113039  113041  113051  113063
  113081  113083  113089  113093  113111  113117  113123  113131  113143  113147
  113149  113153  113159  113161  113167  113171  113173  113177  113189  113209
  113213  113227  113233  113279  113287  113327  113329  113341  113357  113359
  113363  113371  113381  113383  113417  113437  113453  113467  113489  113497
  113501  113513  113537  113539  113557  113567  113591  113621  113623  113647
  113657  113683  113717  113719  113723  113731  113749  113759  113761  113777
  113779  113783  113797  113809  113819  113837  113843  113891  113899  113903
  113909  113921  113933  113947  113957  113963  113969  113983  113989  114001
  114013  114031  114041  114043  114067  114073  114077  114083  114089  114113
  114143  114157  114161  114167  114193  114197  114199  114203  114217  114221
  114229  114259  114269  114277  114281  114299  114311  114319  114329  114343
  114371  114377  114407  114419  114451  114467  114473  114479  114487  114493
  114547  114553  114571  114577  114593  114599  114601  114613  114617  114641
  114643  114649  114659  114661  114671  114679  114689  114691  114713  114743
  114749  114757  114761  114769  114773  114781  114797  114799  114809  114827
  114833  114847  114859  114883  114889  114901  114913  114941  114967  114973
  114997  115001  115013  115019  115021  115057  115061  115067  115079  115099
  115117  115123  115127  115133  115151  115153  115163  115183  115201  115211
  115223  115237  115249  115259  115279  115301  115303  115309  115319  115321
  115327  115331  115337  115343  115361  115363  115399  115421  115429  115459
  115469  115471  115499  115513  115523  115547  115553  115561  115571  115589
  115597  115601  115603  115613  115631  115637  115657  115663  115679  115693
  115727  115733  115741  115751  115757  115763  115769  115771  115777  115781
  115783  115793  115807  115811  115823  115831  115837  115849  115853  115859
  115861  115873  115877  115879  115883  115891  115901  115903  115931  115933
  115963  115979  115981  115987  116009  116027  116041  116047  116089  116099
  116101  116107  116113  116131  116141  116159  116167  116177  116189  116191
  116201  116239  116243  116257  116269  116273  116279  116293  116329  116341
  116351  116359  116371  116381  116387  116411  116423  116437  116443  116447
  116461  116471  116483  116491  116507  116531  116533  116537  116539  116549
  116579  116593  116639  116657  116663  116681  116687  116689  116707  116719
  116731  116741  116747  116789  116791  116797  116803  116819  116827  116833
  116849  116867  116881  116903  116911  116923  116927  116929  116933  116953
  116959  116969  116981  116989  116993  117017  117023  117037  117041  117043
  117053  117071  117101  117109  117119  117127  117133  117163  117167  117191
  117193  117203  117209  117223  117239  117241  117251  117259  117269  117281
  117307  117319  117329  117331  117353  117361  117371  117373  117389  117413
  117427  117431  117