<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_egmkang</title><subtitle type="text">"新的代数语言每5年就走红和过时,而我想要强调的是永恒的概念."   ------By Knuth</subtitle><id>http://feed.cnblogs.com/blog/u/29094/rss</id><updated>2012-04-15T09:55:41Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/29094/rss"/><entry><id>http://www.cnblogs.com/egmkang/archive/2012/04/15/2446713.html</id><title type="text">[boost]使用boost::function和boost::bind产生的down机一例</title><summary type="text">服务器代码依赖了boost的function和bind,用来做回调,异步调用时会出现这种down机.闲话少说上代码:void fn(std::string str);char *temp_str = new char[24];strcpy(temp_str,"1212");boost::function f = boost::bind(fn,temp_str);f();这边的f函数对象里面保存了一个temp_str的指针,如果是同步调用,会有临时的std::string变量产生,产生拷贝一次temp_str,之后就不在引用temp_str,所以不会出现任何问题;可是如果是异</summary><published>2012-04-15T08:59:00Z</published><updated>2012-04-15T08:59:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2012/04/15/2446713.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2012/04/15/2446713.html"/><content type="html">&lt;p&gt;服务器代码依赖了boost的function和bind,用来做回调,异步调用时会出现这种down机.闲话少说上代码:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt; fn(std::&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; str);&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;char&lt;/span&gt; *temp_str = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;char&lt;/span&gt;[&lt;span style="color: #800080;"&gt;24&lt;/span&gt;&lt;span style="color: #000000;"&gt;];&lt;br/&gt;strcpy(temp_str,&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;1212&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br/&gt;boost::function f &lt;/span&gt;=&lt;span style="color: #000000;"&gt; boost::bind(fn,temp_str);&lt;/span&gt;&lt;br/&gt;f();&lt;/div&gt;&lt;p&gt;这边的f函数对象里面保存了一个temp_str的指针,如果是同步调用,会有临时的std::string变量产生,产生拷贝一次temp_str,之后就不在引用temp_str,所以不会出现任何问题;&lt;/p&gt;&lt;p&gt;可是如果是异步调用,temp_str就可能是野指针,如果temp_str被释放了,从const char*构造一个std::string的过程就有可能会down掉.这也就是我们服务器里面一个(一批,准确的说)存在了两年多的Bug.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;虽然知道了Bug的原因,解决办法也会很容易有,就是自己显式的产生一个临时变量,让boost拷贝过去.......&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;std::&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt; temp_string =&lt;span style="color: #000000;"&gt; temp_str;&lt;br/&gt;boost::function f &lt;/span&gt;= boost::bind(fn, temp_string);&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;但是,我在想,为啥boost当初设计的时候,这么蛋疼,为啥不直接保存一个函数参数签名类型的变量,而是保存了一个bind后面的变量.毕竟bind的时候,已经推导出来函数各个参数的准确类型了.如果他直接保存一个签名类型的变量,就不会发生这种问题.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2446713.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2012/04/15/2446713.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2012/01/18/2325474.html</id><title type="text">[C++]怎么样实现一个较快的Hash Table</title><summary type="text">我们服务器一直在用boost/sgl stl的hash table,但是从来没有考虑过其中的效率问题,虽然hash_map/unordered_map跑的可能真的比map快一些,可能应该不是你理解的那么快.其实他可以更快一些!!! 当我自己尝试着实现了一个hash table之后,我发现确实如此.这篇文章也是来说说,如何实现较快的一个. 通常的hash table都是用开链法,开放地址法来解决冲突.开链法是总容易实现的一个,而且因为效率稳定,被加入了C++11,取名unordered_map.不过效率实在不咋地. 开放地址法的hash table,我是从google-sparseha...</summary><published>2012-01-18T06:40:00Z</published><updated>2012-01-18T06:40:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2012/01/18/2325474.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2012/01/18/2325474.html"/><content type="html">&lt;p&gt;我们服务器一直在用boost/sgl stl的hash table,但是从来没有考虑过其中的效率问题,虽然hash_map/unordered_map跑的可能真的比map快一些,可能应该不是你理解的那么快.其实他可以更快一些!!!&lt;/p&gt;&lt;p&gt;当我自己尝试着实现了一个hash table之后,我发现确实如此.这篇文章也是来说说,如何实现较快的一个.&lt;/p&gt;&lt;p&gt;通常的hash table都是用开链法,开放地址法来解决冲突.开链法是总容易实现的一个,而且因为效率稳定,被加入了C++11,取名unordered_map.不过效率实在不咋地.&lt;/p&gt;&lt;p&gt;开放地址法的hash table,我是从google-sparsehash里面注意到的,虽然数据结构,算法导论都会讲到.网上说速度很快,我就去看了一下API,其比普通的unordered_map多了一组API:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1.&amp;nbsp; set_empty_key/set_deleted_key&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在开链法中,所有的节点都是容器内的内容,可是开放地址法中不是的.所以需要额外的信息来维护节点的可用性信息.&lt;/p&gt;&lt;p&gt;当时我看到这两个API,大概就猜到内存是怎么实现的,闲来无事就是试着写了一个demo,在VC 2008下面跑的结果是,比unordered_map快一倍多;在Linux x64 gcc 4.4下面的结果是,比unordered_map快了将近1倍.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. 高性能的hash table必须是开放地址法的&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这么说,是有原因的.链表的特性就是容易删除,容易插入.可是hash table不需要这些特性,hash table只需要快.可以链表这东西,偏偏做不到快速定位,虽然你知道有下一个节点,但是你不知道下一个节点的准确位置,经常会造成缓存未命中,浪费大量时间.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3. bucket的容量&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;bucket的容量也是影响hash table性能的一个因素.无数的数据结构和算法书籍,都教导大家,通过质数取余数,可以获得比较好的下标分布.可是,无论是除法还是乘法,消耗都是相当高的.十几个或者几十个时钟周期,始终比不上一两个时钟周期快.所以,高性能的hash table必须要把bucket的容量设置成2^n.google-sparsehash里面初始容量是32.扩容的话,都是直接左移;算下标的话,都是(容量-1) &amp;amp; hash_value,简单的一个位运算搞定.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;4. 正确实现find_position&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我自己实现的hash table,是线性探测法的.所以find position也是比较简单,就是通过hash value和掩码,获取到其实下标,然后一个一个test.需要把buckets当作是环形的,否则buckets最末位的数据冲突就会不好搞.(我当时没有考虑这一点,直接给他扩容了.....)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;5. 对象模型&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;不同的Key和Value模型,可以导致你对Hash Table的不同实现.简单的说,在C里面,你可以不用考虑Key和Value的生命周期(:D),但是C++里面,你不得不考虑Key,Value的生命周期问题.你不能做一个假设,key和value都是简单数据类型.一个int映射到一个对象,这种经常会用到的.&lt;/p&gt;&lt;p&gt;所以,erase一个key的时候,需要把key设置成deleted,然后还要把value重置一遍.如果没有重置,对象所引用的内存有可能就会被泄露.&lt;/p&gt;&lt;p&gt;这引发了我另外一个想法,就是通过模板,来特化Value的reset行为.因为不是所有的Value都是需要被重置的,只有那些复杂对象,才需要.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;6. 可以考虑缓冲hash value&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果key都是简单数据,而非string或者复杂的数据类型,缓冲是没有任何意义的,因为hash value可以被快速的计算出来;但是当key是char*,或者一些复杂的数据类型,缓冲就会变的有意义.而且缓冲更有利于重排,容器扩容的时候速度会更快一些.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;7. 考虑使用C的内存分配器&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;尽量不要使用C++的new/delete来分配内存.new,delete会有对象的构造,析构过程,这可能不是你所希望的.针对key和value数据类型的不同,你可能会有自己的特有的构造,析构过程.而且,C的内存分配器,同样可以被一些第三方库优化,比如tcmalloc/jemalloc等.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;8. 选一个好的Hash函数&lt;/strong&gt;(&lt;strong&gt;这是最重要的&lt;/strong&gt;)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;差不多就这些.后来自己写的那个demo,性能差不多和google-sparsehash一样...&lt;/p&gt;&lt;p&gt;参考:&lt;/p&gt;&lt;p&gt;1. 算法导论&lt;/p&gt;&lt;p&gt;2. 计算机程序设计艺术&lt;/p&gt;&lt;p&gt;3. google-sparsehash dense_hash_map的实现, &lt;a href="http://code.google.com/p/google-sparsehash" target="_blank"&gt;http://code.google.com/p/google-sparsehash&lt;/a&gt;&lt;/p&gt;&lt;p&gt;PS:&lt;/p&gt;&lt;p&gt;我自己实现了一个:&lt;a href="https://github.com/egmkang/green_turtle/blob/master/collections/hash_table.h" target="_blank"&gt;https://github.com/egmkang/green_turtle/blob/master/collections/hash_table.h&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2325474.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2012/01/18/2325474.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2012/01/18/2325468.html</id><title type="text">[OT]回顾2011,写在2012初</title><summary type="text">2011年都干了些啥....读书:1. 聪明的投资者2. 超级数字天才3. 西游记4. 程序开发心理学5. Unix网络编程6. Unix环境高级编程...或者还有其他的,暂时不记得了技术???....好像没干啥,就天天写代码....搞搞C++,Valgrind,Lua,宕机等等2012年,希望自己可以认真的去写写网络程序,虽然号称是写服务器的,但是从来没写过网络程序;希望可以认真的去看看几个开源的代码,研究一下;over</summary><published>2012-01-18T05:43:00Z</published><updated>2012-01-18T05:43:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2012/01/18/2325468.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2012/01/18/2325468.html"/><content type="html">&lt;p&gt;2011年都干了些啥....&lt;/p&gt;&lt;p&gt;读书:&lt;/p&gt;&lt;p&gt;1. 聪明的投资者&lt;/p&gt;&lt;p&gt;2. 超级数字天才&lt;/p&gt;&lt;p&gt;3. 西游记&lt;/p&gt;&lt;p&gt;4. 程序开发心理学&lt;/p&gt;&lt;p&gt;5. Unix网络编程&lt;/p&gt;&lt;p&gt;6. Unix环境高级编程&lt;/p&gt;&lt;p&gt;...或者还有其他的,暂时不记得了&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;技术???....好像没干啥,就天天写代码....&lt;/p&gt;&lt;p&gt;搞搞C++,Valgrind,Lua,宕机等等&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;2012年,&lt;/p&gt;&lt;p&gt;希望自己可以认真的去写写网络程序,虽然号称是写服务器的,但是从来没写过网络程序;&lt;/p&gt;&lt;p&gt;希望可以认真的去看看几个开源的代码,研究一下;&lt;/p&gt;&lt;p&gt;over&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2325468.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2012/01/18/2325468.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2011/12/27/2303419.html</id><title type="text">[投资]写在11年末</title><summary type="text">大学还没毕业,买了一些建行,一些交行..... 虽然现在还认为那些股票不错,不过终究发生过换股,全换成浦发,古井贡酒,还有鲁泰,出现了一些亏损,记录如下: 其中塔牌,华兰生物是做短线亏损,其他几个本来打算做长线,后来发现收益较好的品种,换股.... 股票名称 交易亏损(RMB) 农业银行 165.95 交通银行 1675.99 建设银行 288.00 三一重工 290.66 苏宁电器 677.41 塔牌集团 281.30 华兰生物 65.72 一共亏损:3445.82. 谨记.</summary><published>2011-12-27T05:27:00Z</published><updated>2011-12-27T05:27:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2011/12/27/2303419.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2011/12/27/2303419.html"/><content type="html">&lt;p&gt;大学还没毕业,买了一些建行,一些交行.....&lt;/p&gt;&lt;p&gt;虽然现在还认为那些股票不错,不过终究发生过换股,全换成浦发,古井贡酒,还有鲁泰,出现了一些亏损,记录如下:&lt;/p&gt;&lt;p&gt;其中塔牌,华兰生物是做短线亏损,其他几个本来打算做长线,后来发现收益较好的品种,换股....&lt;/p&gt;&lt;p&gt;股票名称 &amp;nbsp;&amp;nbsp; &amp;nbsp;交易亏损(RMB)&lt;br /&gt;农业银行 &amp;nbsp;&amp;nbsp; &amp;nbsp;165.95&lt;br /&gt;交通银行 &amp;nbsp;&amp;nbsp; &amp;nbsp;1675.99&lt;br /&gt;建设银行 &amp;nbsp;&amp;nbsp; &amp;nbsp;288.00&lt;br /&gt;三一重工 &amp;nbsp;&amp;nbsp; &amp;nbsp;290.66&lt;br /&gt;苏宁电器 &amp;nbsp;&amp;nbsp; &amp;nbsp;677.41&lt;br /&gt;塔牌集团 &amp;nbsp;&amp;nbsp; &amp;nbsp;281.30&lt;br /&gt;华兰生物 &amp;nbsp;&amp;nbsp; &amp;nbsp;65.72&lt;/p&gt;&lt;p&gt;一共亏损:3445.82.&lt;/p&gt;&lt;p&gt;谨记.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2303419.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2011/12/27/2303419.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2011/10/25/2224561.html</id><title type="text">[C++]运行时,如何确保一个对象是只读的</title><summary type="text">相信很多人碰到过一个问题,就是代码太多了,不知道在哪里把这个对象给修改掉了.这个其实有两种办法的.1. 在调试的时候,可以下数据断点. gdb有watch断点.比如gdb&gt;watch *(int*)0x12433,要记住,如果想要一只监视这个数据,就要用地址,否则过了这个scope,数据断点就无效了,还有就是,监视的值如果用内置数据类型可以表达的话,是有硬件断点的,否则效率茫茫低.....2. 运行的时候,本文主要讲这个. 先来回顾一下,我们都知道一个exec,都有好几个段,比如代码段,数据段等.这些段是有读写属性的,例如代码段只可以读,栈段是可以读写~~.那么我们就想把一个对象塞到一个</summary><published>2011-10-25T14:55:00Z</published><updated>2011-10-25T14:55:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2011/10/25/2224561.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2011/10/25/2224561.html"/><content type="html">&lt;p&gt;相信很多人碰到过一个问题,就是代码太多了,不知道在哪里把这个对象给修改掉了.这个其实有两种办法的.&lt;/p&gt;&lt;p&gt;1. 在调试的时候,可以下数据断点.&lt;/p&gt;&lt;p&gt;gdb有watch断点.比如gdb&amp;gt;watch *(int*)0x12433,要记住,如果想要一只监视这个数据,就要用地址,否则过了这个scope,数据断点就无效了,还有就是,监视的值如果用内置数据类型可以表达的话,是有硬件断点的,否则效率茫茫低.....&lt;/p&gt;&lt;p&gt;2. 运行的时候,本文主要讲这个.&lt;/p&gt;&lt;p&gt;先来回顾一下,我们都知道一个exec,都有好几个段,比如代码段,数据段等.这些段是有读写属性的,例如代码段只可以读,栈段是可以读写~~.那么我们就想把一个对象塞到一个不可以写的段里面,比如.text段....(事实上,我塞进去过,只不过会有警告)&lt;/p&gt;&lt;p&gt;这个异常暴力,而且预留余地太小,不太适合.&lt;/p&gt;&lt;p&gt;现在操作系统都是段模式+分页模式来管理内存的.段模式走不通,换页模式,找个办法设置内存页的属性~~.&lt;/p&gt;&lt;p&gt;非常幸运,Linux下面有mprotect系统调用,可以运行时设置内存页的读写属性,唯一的要求是内存需要4K对齐,浪费了一点.&lt;/p&gt;&lt;p&gt;OK,让我们来看mprotect的man page:&lt;a target="_blank" href="http://linux.die.net/man/2/mprotect"&gt;http://linux.die.net/man/2/mprotect&lt;/a&gt;&lt;/p&gt;&lt;p&gt;签名很简答:int mprotect(const void *addr, size_t len, int prot);&lt;/p&gt;&lt;p&gt;一个地址,一个内存的长度,另外就是读写属性,返回调用的结果,成功返回0,失败返回其他数字.&lt;/p&gt;&lt;p&gt;顺便看看man page中的例子,里面有一个技巧,就是搞到一个4K对齐的内存~~ 通过 ( ptr + 4096 - 1 ) &amp;amp; ~(4096 - 1)搞到的&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br/&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br/&gt;#include &amp;lt;errno.h&amp;gt;&lt;br/&gt;#include &amp;lt;sys/mman.h&amp;gt;&lt;br/&gt;#include &amp;lt;limits.h&amp;gt;    /* for PAGESIZE */&lt;br/&gt;#ifndef PAGESIZE&lt;br/&gt;#define PAGESIZE 4096&lt;br/&gt;#endif&lt;br/&gt;int&lt;br/&gt;main(void)&lt;br/&gt;{&lt;br/&gt;    char *p;&lt;br/&gt;    char c;&lt;br/&gt;    /* Allocate a buffer; it will have the default&lt;br/&gt;       protection of PROT_READ|PROT_WRITE. */&lt;br/&gt;    p = malloc(1024+PAGESIZE-1);&lt;br/&gt;    if (!p) {&lt;br/&gt;        perror("Couldn't malloc(1024)");&lt;br/&gt;        exit(errno);&lt;br/&gt;    }&lt;br/&gt;    /* Align to a multiple of PAGESIZE, assumed to be a power of two */&lt;br/&gt;    p = (char *)(((int) p + PAGESIZE-1) &amp;amp; ~(PAGESIZE-1));&lt;br/&gt;    c = p[666];         /* Read; ok */&lt;br/&gt;    p[666] = 42;        /* Write; ok */&lt;br/&gt;    /* Mark the buffer read-only. */&lt;br/&gt;    if (mprotect(p, 1024, PROT_READ)) {&lt;br/&gt;        perror("Couldn't mprotect");&lt;br/&gt;        exit(errno);&lt;br/&gt;    }&lt;br/&gt;    c = p[666];         /* Read; ok */&lt;br/&gt;    p[666] = 42;        /* Write; program dies on SIGSEGV */&lt;br/&gt;    exit(0);&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;至此,我们就可以运行时,保证一个对象不可以写,写的话,core掉:-D&lt;/p&gt;&lt;p&gt;PS:&lt;/p&gt;&lt;p&gt;希望windows下也有类似的系统调用,Windows下有VirtualProtect,有兴趣的朋友研究一下&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2224561.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2011/10/25/2224561.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2011/10/25/2224529.html</id><title type="text">[C++]怎样将C++对象分配在堆/栈上</title><summary type="text">相信一些朋友也碰见过这样的面试题目,本文尝试着给出解答.1. 分配对象在堆上 那么,必然要禁止对象在栈上面分配.一个很简单的办法,就是构造函数私有化(提供额外的接口生成对象),那么在栈上面就不可以分配.可是我们还需要这个对象要被析构,那么可以提供一个接口,显式的释放掉这个接口,也就是说delete也得给他禁掉~~~ 考虑另外一个问题,C++有placement new,我自己new一块内存,然后在你这上面构造.问题就变得很恶心,看来我们只有把new,delete都给他禁掉... 好了,我们现在知道该怎么做:createInstance()接口产生对象dispose()接口销毁对象new/...</summary><published>2011-10-25T14:40:00Z</published><updated>2011-10-25T14:40:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2011/10/25/2224529.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2011/10/25/2224529.html"/><content type="html">&lt;p&gt;相信一些朋友也碰见过这样的面试题目,本文尝试着给出解答.&lt;/p&gt;&lt;p&gt;1. 分配对象在堆上&lt;/p&gt;&lt;p&gt;那么,必然要禁止对象在栈上面分配.一个很简单的办法,就是构造函数私有化(提供额外的接口生成对象),那么在栈上面就不可以分配.可是我们还需要这个对象要被析构,那么可以提供一个接口,显式的释放掉这个接口,也就是说delete也得给他禁掉~~~&lt;/p&gt;&lt;p&gt;考虑另外一个问题,C++有placement new,我自己new一块内存,然后在你这上面构造.问题就变得很恶心,看来我们只有把new,delete都给他禁掉...&lt;/p&gt;&lt;p&gt;好了,我们现在知道该怎么做:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;createInstance()接口产生对象&lt;/li&gt;&lt;li&gt;dispose()接口销毁对象&lt;/li&gt;&lt;li&gt;new/delete操作符全部不可见&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;来看我们的代码:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class HeapObject{&lt;br/&gt;public:&lt;br/&gt;static HeapObject* createInstance()&lt;br/&gt;{&lt;br/&gt;return new HeapObject;&lt;br/&gt;}&lt;br/&gt;void dispose()&lt;br/&gt;{&lt;br/&gt;delete this;&lt;br/&gt;}&lt;br/&gt;protected:&lt;br/&gt;HeapObject(){}&lt;br/&gt;~HeapObject(){}&lt;br/&gt;&lt;br/&gt;static void* operator new (std::size_t size) throw (std::bad_alloc)&lt;br/&gt;{&lt;br/&gt;return ::operator new(size);&lt;br/&gt;}&lt;br/&gt;static void* operator new (std::size_t size, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void* operator new (std::size_t size, void* ptr) throw();&lt;br/&gt;static void* operator new[] (std::size_t size) throw (std::bad_alloc);&lt;br/&gt;static void* operator new[] (std::size_t size, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void* operator new[] (std::size_t size, void* ptr) throw();&lt;br/&gt;&lt;br/&gt;static void operator delete (void* ptr) throw ()&lt;br/&gt;{&lt;br/&gt;::operator delete(ptr);&lt;br/&gt;}&lt;br/&gt;static void operator delete (void* ptr, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void operator delete (void* ptr, void* voidptr2) throw();&lt;br/&gt;&lt;br/&gt;static void operator delete[] (void* ptr) throw ();&lt;br/&gt;static void operator delete[] (void* ptr, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void operator delete[] (void* ptr, void* voidptr2) throw();&lt;br/&gt;};&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;2. 分配对象在栈上&lt;/p&gt;&lt;p&gt;只能分配对象在栈上面,那么new显然是不能用的,否则就是在堆上面分配对象了,理所当然,delete也得禁掉.&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class StackObject&lt;br/&gt;{&lt;br/&gt;public:&lt;br/&gt;StackObject(){}&lt;br/&gt;~StackObject(){}&lt;br/&gt;protected:&lt;br/&gt;static void* operator new (std::size_t size) throw (std::bad_alloc);&lt;br/&gt;static void* operator new (std::size_t size, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void* operator new (std::size_t size, void* ptr) throw();&lt;br/&gt;static void* operator new[] (std::size_t size) throw (std::bad_alloc);&lt;br/&gt;static void* operator new[] (std::size_t size, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void* operator new[] (std::size_t size, void* ptr) throw();&lt;br/&gt;&lt;br/&gt;static void operator delete (void* ptr) throw ();&lt;br/&gt;static void operator delete (void* ptr, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void operator delete (void* ptr, void* voidptr2) throw();&lt;br/&gt;&lt;br/&gt;static void operator delete[] (void* ptr) throw ();&lt;br/&gt;static void operator delete[] (void* ptr, const std::nothrow_t&amp;amp; nothrow_constant) throw();&lt;br/&gt;static void operator delete[] (void* ptr, void* voidptr2) throw();&lt;br/&gt;};&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;比较需要注意的地方是,new/delete有多个重载,算上[]的话,就是3*2*2=12个操作符.....&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2224529.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2011/10/25/2224529.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2011/09/27/2193096.html</id><title type="text">[Lua]用__index/__newindex来限制访问</title><summary type="text">网友问了一个问题,说对象A在内部可以修改HP.外部对象只能访问对象A的HP,不能修改.这东西其实可以用__index和__newindex来实现.__index指向对象A,这样就可以访问;__newindex重写,修改hp的话,就禁止.就可以完成他的需求.下面给出简单的代码:function cannotModifyHp(object) local proxy = {} local mt = { __index = object,__newindex = function(t,k,v) if k ~= "hp" then object[k] = v en...</summary><published>2011-09-27T06:16:00Z</published><updated>2011-09-27T06:16:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2011/09/27/2193096.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2011/09/27/2193096.html"/><content type="html">&lt;p&gt;网友问了一个问题,说对象A在内部可以修改HP.外部对象只能访问对象A的HP,不能修改.&lt;/p&gt;&lt;p&gt;这东西其实可以用__index和__newindex来实现.&lt;/p&gt;&lt;p&gt;__index指向对象A,这样就可以访问;&lt;/p&gt;&lt;p&gt;__newindex重写,修改hp的话,就禁止.就可以完成他的需求.&lt;/p&gt;&lt;p&gt;下面给出简单的代码:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;function cannotModifyHp(object)&lt;br/&gt;    local proxy = {}&lt;br/&gt;    local mt = {&lt;br/&gt;    __index = object,&lt;br/&gt;__newindex = function(t,k,v)&lt;br/&gt;    if k ~= "hp" then&lt;br/&gt;object[k] = v&lt;br/&gt;    end&lt;br/&gt;end&lt;br/&gt;    }&lt;br/&gt;    setmetatable(proxy,mt)&lt;br/&gt;    return proxy&lt;br/&gt;end&lt;br/&gt;&lt;br/&gt;object = {hp = 10,age = 11}&lt;br/&gt;function object.sethp(self,newhp)&lt;br/&gt;self.hp = newhp&lt;br/&gt;end&lt;br/&gt;&lt;br/&gt;o = cannotModifyHp(object)&lt;br/&gt;&lt;br/&gt;o.hp = 100&lt;br/&gt;print(o.hp)&lt;br/&gt;&lt;br/&gt;o:sethp(111)&lt;br/&gt;print(o.hp)&lt;br/&gt;&lt;br/&gt;object:sethp(100)&lt;br/&gt;print(o.hp)&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;PS:&lt;/p&gt;&lt;p&gt;好长时间没写过lua了,都快忘了&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2193096.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2011/09/27/2193096.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2011/09/26/2189548.html</id><title type="text">[C++]野指针的产生以及应对办法</title><summary type="text">很大程度上,野指针都是因为编码不善,习惯不好所产生的.要解决野指针,就要养成好习惯,不要动不动就public数据成员,所有的数据访问都抽象成接口,最好只在一个地方delete数据.前段时间游戏技术测试,down机无限,搞的很头疼.后来用valgrind的memcheck工具,找到很多野指针.valgrind很好用,除了有一点慢:-)valgrind --tool=memcheck --leak-check=full --log-file=./log_file.log --showpossibly-lost=no --malloc-fill=0xff --free-fill=0x11 ./exe</summary><published>2011-09-26T14:51:00Z</published><updated>2011-09-26T14:51:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2011/09/26/2189548.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2011/09/26/2189548.html"/><content type="html">&lt;p&gt;很大程度上,野指针都是因为编码不善,习惯不好所产生的.&lt;/p&gt;&lt;p&gt;要解决野指针,就要养成好习惯,不要动不动就public数据成员,所有的数据访问都抽象成接口,最好只在一个地方delete数据.&lt;/p&gt;&lt;p&gt;前段时间游戏技术测试,down机无限,搞的很头疼.后来用valgrind的memcheck工具,找到很多野指针.&lt;/p&gt;&lt;p&gt;valgrind很好用,除了有一点慢:-)&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;valgrind --tool=memcheck --leak-check=full --log-file=./log_file.log --showpossibly-lost=no --malloc-fill=0xff --free-fill=0x11 ./execFile&lt;br/&gt;&lt;/div&gt;&lt;p&gt;用上面的语句,就可以启动一个execFile,顺便把所有malloc内存设置成0xff,free内存设置成0x11,还会统计内存泄露(在log_file.log内).简单易用.&lt;/p&gt;&lt;p&gt;然后么,一个一个去fix....&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;跟同学交流,他们那边有一个办法,去解决这个野指针问题,也是很巧妙的,不敢独享:-D&lt;/p&gt;&lt;p&gt;A对象会被n个其他对象B引用,就是其他n个对象B会持有指向A的指针.&lt;/p&gt;&lt;p&gt;如果A被delete,其他n个对象B指向A的指针的内存已经不可访问,这个时候访问那块内存,就会发生未定义行为.&lt;/p&gt;&lt;p&gt;天知道会怎么样!!!也许会down掉,也许不会.&lt;/p&gt;&lt;p&gt;他们是搞的:&lt;/p&gt;&lt;p&gt;1) 对象B对A的引用,A自己会保存一份记录,标记有对象B引用过自己&lt;/p&gt;&lt;p&gt;2) 对象B析构,会通知A,这个时候,A会去除B对自己的引用的标记&lt;/p&gt;&lt;p&gt;3) A析构,A会把所有指向自己的指针,设置成NULL&lt;/p&gt;&lt;p&gt;这是基本思想.&lt;/p&gt;&lt;p&gt;下面给出简单的实现,非线程安全,有什么问题可以提出...&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;#ifndef __REFERABLE_H__&lt;br/&gt;#define __REFERABLE_H__&lt;br/&gt;&lt;br/&gt;#include &amp;lt;vector&amp;gt;&lt;br/&gt;#include "ref_ptr.h"&lt;br/&gt;&lt;br/&gt;template&amp;lt;typename T&amp;gt;&lt;br/&gt;class referable&lt;br/&gt;{&lt;br/&gt;public:    &lt;br/&gt;    typedef referable** RefAddress;&lt;br/&gt;    virtual ~referable()&lt;br/&gt;    {&lt;br/&gt;        for (container_iter iter = m_references.begin();&lt;br/&gt;            iter != m_references.end();&lt;br/&gt;            ++iter)&lt;br/&gt;        {&lt;br/&gt;            **iter = NULL; &lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;private:&lt;br/&gt;    typedef typename std::vector&amp;lt;RefAddress&amp;gt; container_type;&lt;br/&gt;    typedef typename container_type::iterator container_iter;&lt;br/&gt;&lt;br/&gt;    friend class ref_ptr&amp;lt;T&amp;gt;;&lt;br/&gt;    void on_reg(RefAddress addr)&lt;br/&gt;    {&lt;br/&gt;        for (container_iter iter = m_references.begin();&lt;br/&gt;            iter != m_references.end();&lt;br/&gt;            ++iter)&lt;br/&gt;        {&lt;br/&gt;            if(*iter == addr) return;&lt;br/&gt;        }&lt;br/&gt;        m_references.push_back(addr);&lt;br/&gt;    }&lt;br/&gt;    void on_unreg(RefAddress addr)&lt;br/&gt;    {&lt;br/&gt;        for (container_iter iter = m_references.begin();&lt;br/&gt;            iter != m_references.end();)&lt;br/&gt;        {&lt;br/&gt;            if(*iter == addr)&lt;br/&gt;                iter = m_references.erase(iter);&lt;br/&gt;            else&lt;br/&gt;                ++iter;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;private:&lt;br/&gt;    container_type m_references;&lt;br/&gt;};&lt;br/&gt;#endif&lt;br/&gt;&lt;/div&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;#ifndef __REFERENCE_POINTER_H__&lt;br/&gt;#define __REFERENCE_POINTER_H__&lt;br/&gt;#include "referable.h"&lt;br/&gt;&lt;br/&gt;template&amp;lt;typename T&amp;gt;&lt;br/&gt;class ref_ptr&lt;br/&gt;{&lt;br/&gt;public:&lt;br/&gt;    ref_ptr():m_ptr(NULL){}&lt;br/&gt;    ref_ptr(T *ptr):m_ptr(ptr)&lt;br/&gt;    {&lt;br/&gt;        add_ref();&lt;br/&gt;    }&lt;br/&gt;    ref_ptr(const ref_ptr&amp;lt;T&amp;gt;&amp;amp; ref):m_ptr(ref.m_ptr)&lt;br/&gt;    {&lt;br/&gt;        add_ref();&lt;br/&gt;    }&lt;br/&gt;    virtual ~ref_ptr()&lt;br/&gt;    {&lt;br/&gt;        remove_ref();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    ref_ptr&amp;lt;T&amp;gt;&amp;amp; operator = (const ref_ptr&amp;lt;T&amp;gt;&amp;amp; ref)&lt;br/&gt;    {&lt;br/&gt;        if(this == &amp;amp;ref) return *this;&lt;br/&gt;        remove_ref();&lt;br/&gt;        m_ptr = ref.m_ptr;&lt;br/&gt;        add_ref();&lt;br/&gt;        return *this;&lt;br/&gt;    }&lt;br/&gt;    ref_ptr&amp;lt;T&amp;gt;&amp;amp; operator = (T *ptr)&lt;br/&gt;    {&lt;br/&gt;        if(m_ptr != ptr)&lt;br/&gt;        {&lt;br/&gt;            remove_ref();&lt;br/&gt;            m_ptr = ptr;&lt;br/&gt;            add_ref();&lt;br/&gt;        }&lt;br/&gt;        return *this;&lt;br/&gt;    }&lt;br/&gt;public:&lt;br/&gt;    T*  operator-&amp;gt;() const { return m_ptr; }&lt;br/&gt;    T&amp;amp;  operator*() const { return *m_ptr; }&lt;br/&gt;    operator T*() const { return m_ptr; }&lt;br/&gt;    operator bool() const { return m_ptr; }&lt;br/&gt;private:&lt;br/&gt;    void add_ref()&lt;br/&gt;    {&lt;br/&gt;        if(m_ptr) ((referable&amp;lt;T&amp;gt;*)m_ptr)-&amp;gt;on_reg((referable&amp;lt;T&amp;gt;**)&amp;amp;m_ptr);&lt;br/&gt;    }&lt;br/&gt;    void remove_ref()&lt;br/&gt;    {&lt;br/&gt;        if(m_ptr) ((referable&amp;lt;T&amp;gt;*)m_ptr)-&amp;gt;on_unreg((referable&amp;lt;T&amp;gt;**)&amp;amp;m_ptr);&lt;br/&gt;        m_ptr = NULL;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;private:&lt;br/&gt;    T* m_ptr;&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;#endif&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;测试代码:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class object : public referable&amp;lt;object&amp;gt;&lt;br/&gt;{&lt;br/&gt;public:&lt;br/&gt;    int x;&lt;br/&gt;};&lt;br/&gt;&lt;br/&gt;void test()&lt;br/&gt;{&lt;br/&gt;    object *a = new object;&lt;br/&gt;    object *a1 = new object;&lt;br/&gt;    ref_ptr&amp;lt;object&amp;gt; b = a;&lt;br/&gt;    a-&amp;gt;x = 10;&lt;br/&gt;    assert(b &amp;amp;&amp;amp; b-&amp;gt;x == 10);&lt;br/&gt;&lt;br/&gt;    delete a;&lt;br/&gt;    assert(!b);&lt;br/&gt;&lt;br/&gt;    b = a1;&lt;br/&gt;    assert(b);&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;这个东西看上去还不错.&lt;/p&gt;&lt;p&gt;不过习惯还是很重要滴&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;PS:&lt;/p&gt;&lt;p&gt;一般引用都是只有四五个,所以vector性能足够好,我测试过~~&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2189548.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2011/09/26/2189548.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2011/08/13/2125500.html</id><title type="text">[投资]浦发银行的价值投资</title><summary type="text">CPI那么高,为了抗通胀,我买了股票,号称是价值投资:-),可是一直没有算过具体能有多少收益....今天算了一下浦发银行的收益,不算不知道,一算吓一跳啊.去年年报每股净资产8.57RMB,今年由于分割了股票,所以每股净资产大约是(8.99+0.42)/1.3 = 7.2RMB,作为起始每股净资产然后假设每年的净资产收益率为15%,去年是15.59%,据以往历史,15%的净资产收益率还是比较容易达到的.算算5年,10年后,浦发的净资产有多少:7.2(1+0.15)^5 = 14.487.2*(1+0.15)^10 = 29.12银行牛市时,PB会比较高一点,3倍算是比较高的,那么大约可以估算出1</summary><published>2011-08-13T11:22:00Z</published><updated>2011-08-13T11:22:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2011/08/13/2125500.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2011/08/13/2125500.html"/><content type="html">&lt;p&gt;CPI那么高,为了抗通胀,我买了股票,号称是价值投资:-),可是一直没有算过具体能有多少收益....&lt;/p&gt;&lt;p&gt;今天算了一下浦发银行的收益,不算不知道,一算吓一跳啊.&lt;/p&gt;&lt;p&gt;去年年报每股净资产8.57RMB,今年由于分割了股票,所以每股净资产大约是(8.99+0.42)/1.3 = 7.2RMB,作为起始每股净资产&lt;/p&gt;&lt;p&gt;然后假设每年的净资产收益率为15%,去年是15.59%,据以往历史,15%的净资产收益率还是比较容易达到的.&lt;/p&gt;&lt;p&gt;算算5年,10年后,浦发的净资产有多少:&lt;/p&gt;&lt;p&gt;7.2(1+0.15)^5&amp;nbsp; = 14.48&lt;/p&gt;&lt;p&gt;7.2*(1+0.15)^10 = 29.12&lt;/p&gt;&lt;p&gt;银行牛市时,PB会比较高一点,3倍算是比较高的,那么大约可以估算出10年后浦发的合理估值是大约60元;如果能达到8倍PB,那就是240RMB.&lt;/p&gt;&lt;p&gt;浦发达到过8倍PB哈:-)&lt;/p&gt;&lt;p&gt;爱股网有一堆做价值投资的网游,有兴趣的话进去看看&lt;br /&gt;&lt;a target="_blank" href="http://www.iguuu.com/?fromuser=egmkang"&gt;http://www.iguuu.com/?fromuser=egmkang&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2125500.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2011/08/13/2125500.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/egmkang/archive/2011/07/16/2108078.html</id><title type="text">[vim]我的vim配置</title><summary type="text">set nocompatibleset backspace=indent,eol,startset nobackupset history=50set rulerset showcmdset showmatchset hlsearchset incsearchset ignorecasesyntax onfiletype plugin indent onautocmd FileType text setlocalset autoindentset cindentset numberset expandtabset tabstop=4set shiftwidth=4set nowrapset l</summary><published>2011-07-16T03:16:00Z</published><updated>2011-07-16T03:16:00Z</updated><author><name>egmkang</name><uri>http://www.cnblogs.com/egmkang/</uri></author><link rel="alternate" href="http://www.cnblogs.com/egmkang/archive/2011/07/16/2108078.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/egmkang/archive/2011/07/16/2108078.html"/><content type="html">&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;set nocompatible&lt;br/&gt;set backspace=indent,eol,start&lt;br/&gt;set nobackup&lt;br/&gt;set history=50&lt;br/&gt;set ruler&lt;br/&gt;set showcmd&lt;br/&gt;&lt;br/&gt;set showmatch&lt;br/&gt;set hlsearch&lt;br/&gt;set incsearch&lt;br/&gt;set ignorecase&lt;br/&gt;&lt;br/&gt;syntax on&lt;br/&gt;filetype plugin indent on&lt;br/&gt;autocmd FileType text setlocal&lt;br/&gt;&lt;br/&gt;set autoindent&lt;br/&gt;set cindent&lt;br/&gt;set number&lt;br/&gt;set expandtab&lt;br/&gt;set tabstop=4&lt;br/&gt;set shiftwidth=4&lt;br/&gt;set nowrap&lt;br/&gt;&lt;br/&gt;set listchars=tab:&amp;gt;\ ,trail:-&lt;br/&gt;set list&lt;br/&gt;&lt;br/&gt;set path+=STL_PAT&lt;br/&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://files.cnblogs.com/egmkang/_vimrc.js"&gt;vimrc地址&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/egmkang/aggbug/2108078.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/egmkang/archive/2011/07/16/2108078.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
