分类目录: C/C++
扫描目录自动生成VS2005/2008工程文件
对于喜欢使用Visual Studio看代码和写代码的同学而言,没有VS工程,手动建工程通常是一件非常痛苦的事情。之前一直使用一个叫做MPC的工具生成各个版本的VS工程文件,该工具依赖perl语言,而且只能遍历一级目录,不能递归到所有的子目录(也可能工具提供,但是是我没有深入研究工具的配置),而且工具集成到右键菜单,不是经常使用的功能集成到右键菜单不是很好。重新安装了操作系统后,再也不想安装复杂的MPC了,在网上找新的替代工具,找到了如下网址提供的DIY式的工具:链接。
感觉工具中写死工程名字不是很好,稍作了一点修改。使用目录名作为工程名,同时省去了第三个参数。这样只需要将目录拖拽到工具上面就可以在目录内部生成一个与目录名同名的工程文件。该工程文件为VS2005和VS2008兼容的vcxproj格式的文件。对于高版本打开该工具生成的工程时,打开时,会提示升级。以下代码在VS2013编译通过。
关于回调函数和this指针探讨
在C里面,经常需要提供一个函数地址,注册到结构里,然后在程序执行到特定阶段时,回调该函数。创建线程,注册线程运行的主函数就是一个典型的例子。这里以简单的回调实例,说明C++中回调函数为成员函数时有关this指针的问题。由于C++对C的继承关系,C++没有自己的线程封装技术,一般而言我们创建线程时,还是用C的回调函数机制。类似的例子也挺多的。在Java等纯粹的面向对象语言,则不一样,不光有自己的独立的线程类型,对于回调,也是注册整个对象,而不是注册一个方法,如常用的观察者模式。这里,在网上查阅了大量关于this指针、类成员函数和静态成员函数的相关知识点,结合自己的理解作一些总结。
关于虚函数表那点事儿
今天看到有文章介绍Visual Studio C++有一个编译选项:/d1 reportAllClassLayout,用来输出所有的类型信息,比较有趣。如下图,在工程,属性,编译的命令行中,增加一个“其他选项”,填写/d1 reportAllClassLayout即可。在编译类时,就会生成类的内存结构图。包括虚函数指针表。
15道使用频率极高的基础算法题
从一个非典型的内存越界访问问题看Linux的进程内存布局
这篇文章想以一个内存越界问题分析过程来说明进程的内存布局。问题有点巧合,程序刚好没有出现segment fault,而是继续在运行,却出现了很诡异的结果。
实例说明:编写一个对Linux消息队列的测试程序,同时提供收发程序,接收程序使用NOWAIT的方式来接收,发送端每隔一段时间发送一个消息。接收端和发送端都作一个操作次数统计,接收端的读取间隔时间设置较短,因此存在消息队列为空的情况,在此情况下,只做计数,休眠较短时间后继续下一次读取。
测试出问题程序的代码如下:
基于C语言的hash table实现进程内缓存
最近遇到一个问题需要做本地缓存,首先想到就是hash表。如果是java,太easy了。C语言就是需要不停的造轮子,实在不想写这个面试题样的东西了,求助于万能的Google了。找到一个不错的hashtable开源实现:http://troydhanson.github.io/uthash/,BSD的许可,赞。也找到了一篇文章介绍详细的用法:http://blog.csdn.net/hongqun/article/details/6103275。
设计模式,学以致用—Proxy模式
最近在恶补设计模式的知识,GoF的23种设计模式都囫囵吞枣的看了一遍,貌似每一种模式都看懂了。然而到底有没有掌握各种模式呢,遇到实际问题时能否正确处理,还是需要打一个大大的问号。这里就遇到一个实际问题需要用模式来解决,然而我拿到这个问题的时候第一时间想到的却不是用模式,走了不少弯路。
问题如下:拿到了如下接口和库文件。需求是,不想把这个原始的接口暴露给用户,希望将真实的接口做一个简单的隐藏,对这套接口进行一个封装,在客户调用doSmth之前,还能做一些别的事情,诸如做一些额外的初始化。也就是对一个动态库文件和接口进行二次封装。
DRBD源码分析(三)——块设备驱动和IO队列处理函数
很长时间没有继续这个源码分析了,原因是到了主流业务,对底层的驱动知识不太了解,也没有太多时间。
在上一节中分析到
STATIC void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms *nsp)
mdev = ensure_mdev(nlp);
在这个调用中,会进行设备的注册和驱动的加载。这一节重点分析struct drbd_conf* drbd_new_device(unsigned int minor)方法。该方法主要是一个块设备的驱动。关于块设备的驱动程序的编写,可以参考CU上面的赵磊的帖子,该帖子绘声绘色的讲解了如何从0基础开始编写块设备驱动:链接。
对于每一个块设备,会进行一系列的初始化,会启动3个内核线程:
drbd_thread_init(mdev, &mdev->receiver, drbdd_init);
drbd_thread_init(mdev, &mdev->worker, drbd_worker);
drbd_thread_init(mdev, &mdev->asender, drbd_asender);