曲径通幽

programming_with_fun();

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  18 Posts :: 0 Stories :: 5 Comments :: 0 Trackbacks

常用链接

留言簿(6)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

2012年6月26日 #

按照libevent的文档,使用VC的nmake -f Makefile.nmake即可编译32位release模式。
因为项目中要求编译64位的版本,需要在Makefile.nmake中添加一个LIBFLAGS选项 /MACHINE:X64
如果要加调试信息,可以在 CFLAGS中加入/Zi,32位加调试选项是 CFLAGS中加/ZI,当然要调整优化选项/Ox
posted @ 2012-06-26 14:54 Meiosis 阅读(3391) | 评论 (0)编辑 收藏

2012年6月6日 #

记得以前解决过这个问题,现在帮助同事查BUG的时候,再次遇到,记录一下省的下次再苦苦回忆。
遇到这个问题,一般而言是3种情况造成:
1) 其他线程、进程正在执行一次写操作
    根据SQLITE文档,所有写操作(当然SELECT不算写操作),SQLITE内部都会自动添加事务,这样在线程同时写有依赖关系的表的时候,自然会发生冲突
2) 当前SQLITE被“BEGIN TRANSACTION” lock住了,这个问题其实包含了1)中的隐形调用,另外别忘了自己的代码一定要在执行完BEGIN 后 COMMIT
3) 有statement对象未finalize,且未reset(出错时)
    这个情况占多数,我项目中遇到两次都是这个情况,
    当然,要注意即使自己未直接调用 prepare-step-finalize,在某些API执行的时候会隐式调用(比如sqlite3_exec),当然这种情况一般会归在1)里
   
posted @ 2012-06-06 16:35 Meiosis 阅读(1109) | 评论 (0)编辑 收藏

2012年6月5日 #

@note: 只在windows中测试,未在linux上跑过
方法一: 通过宏传递
例如
void myprintf(const char* format, );

3 #ifndef PASS_ARGS
#define PASS_ARGS(_fmt,) \
5   myprintf(fmt,__VA_ARGS__)
#endif

这种方式最简单最直接,但不利于函数的封装调用。

方法二: 通过函数传递
 2 
 3 void myprintf(const char* fmt, )
 4 {
 5     va_list args;
 6     va_start(args, fmt);
 7     myprintf_internal(fmt, args);
 8     va_end(args);
 9 }
这种方法可以在函数内传递 va_list

至于 myprintf(const char*, ...) 传给 myprintf_internal(const char*, ...)这种方式,貌似只能通过循环解析出实参个数和内容,再传递给下一个函数,感觉上这样做可能会存在性能损耗
posted @ 2012-06-05 17:53 Meiosis 阅读(1682) | 评论 (0)编辑 收藏

2012年4月27日 #

直接用自带的 screen 即可解决,screen 中执行的任务 c-a d 之后会把任务切后台,
重新SSH上去之后,screen -ls 找到ID,直接 screen -r [id]

C-a ? 显示所有键绑定信息
C-a w 显示所有窗口列表
C-a C-a 切换到之前显示的窗口
C-a c 创建一个新的运行shell的窗口并切换到该窗口
C-a n 切换到下一个窗口
C-a p 切换到前一个窗口(与C-a n相对)
C-a 0..9 切换到窗口0..9
C-a a 发送 C-a到当前窗口
C-a d 暂时断开screen会话
C-a k 杀掉当前窗口
C-a [ 进入拷贝/回滚模式
posted @ 2012-04-27 00:17 Meiosis 阅读(1322) | 评论 (0)编辑 收藏

2012年3月30日 #

在工作中遇到windbg需要打开mini dump文件,MARK一下。
!analyze -v 
posted @ 2012-03-30 14:30 Meiosis 阅读(507) | 评论 (0)编辑 收藏

2012年1月19日 #

项目里遇到一个问题,在我们程序客户端运行时,sqlite数据库会不断自动生成/删除 journal 文件,高峰时候会占用大量的IO,导致程序很慢。
由于客户端本身的数据完整性不重要,性能非常重要,所以想禁止这个文件的生成。
后来查了一下文档,并实践过后,发现网络上所有的关于关闭/打开某些宏来防止生成的方法都不管用。情急之下,只有改源码了。
改的地方是在main.c 的 sqlite3BtreeFactory 里,直接加个宏就好了 omitJournal

 1 int sqlite3BtreeFactory(
 2   const sqlite3 *db,        /* Main database when opening aux otherwise 0 */
 3   const char *zFilename,    /* Name of the file containing the BTree database */
 4   int omitJournal,          /* if TRUE then do not journal this file */
 5   int nCache,               /* How many pages in the page cache */
 6   int vfsFlags,             /* Flags passed through to vfsOpen */
 7   Btree **ppBtree           /* Pointer to new Btree object written here */
 8 ){
 9   int btFlags = 0;
10   int rc;
11   
12   assert( sqlite3_mutex_held(db->mutex) );
13   assert( ppBtree != 0);
14 
15 #ifdef OMIT_JOURNAL
16   omitJournal = 1; //!< turn off journal file
17 #endif

posted @ 2012-01-19 17:58 Meiosis 阅读(499) | 评论 (0)编辑 收藏

2011年9月20日 #

环境:
   WinXP-SP3(chs) + VS2010-SP1(en-us) + boost 1.47.0 + python 2.7(ActivePython2.7 携带)

   boost编译时,boost::python库编译为 stage debug release link=static runtime-link=shared

问题1:
   python27 不认dll作为extension
解决方案:
   project的output file 和 extension 都设置为 .pyd

问题2:
   需要在导出类函数时,支持带指针的参数 (重头戏)
解决方案:
   这个问题似乎网上没有一个完整的答案,零零碎碎的问题有一堆,但感觉都不到位,接下来我就给个方案吧。(我对boost::python也不熟,如有错误希望好言指正:) )

 1 #include <boost/python.hpp>
 2 #include <stdio.h>
 3 using namespace boost::python;
 4 
 5 struct World
 6 {
 7     void simpleHello(void)
 8     {
 9         printf("this is simple hello\n");
10     }
11     void hello(int *data)
12     {
13         printf("World say hello :%d\n"*data);
14     }
15     int* ready(void)
16     {
17         return new int(1234);
18     }
19 };
20 
21 BOOST_PYTHON_MODULE(sample)
22 {
23     class_<World>("World")
24     .def("simpleHello"&World::simpleHello)
25     .def("hello"&World::hello, arg("data"))
26     .def("ready"&World::ready, return_value_policy<return_opaque_pointer>())
27     ;
28 }

这里要说明二点:
1)这个例子既有传指针参数,又有返回指针对象,算是把boost::python两个典型问题囊括了。
2)return_opaque_pointer 是我查官方文档后得到的一个变通(官方推荐这里用 manage_new_object,但不管你编不编的过,反正我是编不过,在翻了Reference manual后看到了 opaque_pointer,看名字觉得有戏,就拿来用了。貌似opaque_pointer的严格性更低一点。编译通过,运行OK,反正就这样了)
posted @ 2011-09-20 14:29 Meiosis 阅读(2368) | 评论 (3)编辑 收藏

2011年6月14日 #

  ZeroMQ是一个Message Queue的实现方案,支持超多种语言的Binding,今天研究了一下,起初对它的N:N模型很感兴趣,后来试用了其自带的 Load Balance特性,结果发现一个非常严重的问题,在Server Cluster中,如果有一台服务器在接收消息后Blocking,或者服务器崩溃了,没来得及send response,则客户端的请求一直就停留在这次send req上,永远无法检测出error,我查了关于timeout的文档,后来改用poll模型试了很久,还是没法解决。接下来可能要花时间仔细研读一下Guide了。
posted @ 2011-06-14 16:59 Meiosis 阅读(1246) | 评论 (1)编辑 收藏

2011年6月13日 #

  最近在工作中发现网络通信收发文件部分,发送一次文件后,就再也不能发第二次了。本以为是协议的问题,后来用TOP发现CPU过高,才通过GDB看到了是一个清空Buffer类的代码有BUG,计算无符号整形的操作溢出了。
  具体跟踪方法记录一下。首先正常启动程序,然后进行收发文件操作,触发死循环。而后通过 top -H 查看哪个线程(其实是PID,redhat的线程是fork进程实现的)占用CPU过高,而后gdb -p [pid] attach 之,最后bt 打印堆栈。
posted @ 2011-06-13 13:49 Meiosis 阅读(554) | 评论 (0)编辑 收藏

2011年1月6日 #

这是从别人博客上摘的一段C嵌汇编码
( http://www.cppblog.com/kevinlynx/archive/2011/01/02/137886.html )
__declspec(naked)
void caller(void* pfn, 
{
    __asm 
    {
        pop eax;
        add eax, 3;
        xchg dword ptr[esp], eax;
        push eax;
        ret;
    }
}
下面是调用方法
void print_str( const char *s )
{
    printf( "%s\n", s );
}

{
   ...
caller( print_str, "a string" );
   __asm  add esp, 4
   ...
}

  原作者讲了一些基础,这里就不提了
看了一遍,发现 "ADD EAX, 3" 的用法有点奇怪(我相信搞破解的人一定比较熟悉,但正常的程序不会这么写。)
初看 EAX 是地址,+3是很危险的,但仔细一看,发现代码是为了从最外层主调函数一路穿越"caller" 直达 print_str,这里牵涉到一个重要问题,就是在CALL指令时,会有将“CALL指令下一条地址压栈”的操作,那么代码思路很明了了,就是为了要造出 调用print_str时,ESP(+0) 指向 caller(..)调用的下一个地址。
  第一关已经顺利搞定,但又碰到个问题,由于 print_str 的入参是可变的,所以必须用 cdecl调用,那RET之后 如何平栈呢? 如果直接跳到 caller下一条地址,就丧失了平栈的机会,最终会在某个主调函数上被微软的 stack cookie捕获抛个SEH。
  这里就用到文章开头提到的 ADD EAX, 3。
  必须要造一个环境,让 caller 调用完成后,给个机会清理现场。于是乎,caller之后就有了 ADD ESP, 4。其实这里的4是与print_str的入参数目相关的,每个参数要多加 4字节,如此一来,整个代码就理顺了。
  那为什么 是 ADD EAX, 3呢? 应该是预估出一条ADD指令占用多少长度,和具体的环境有关。因为没看INTEL手册,这里只能认为ADD 寄存器+WORD的长度是3个字节。我用VC试验了一下,的确是如此,我也尝试了ADD 寄存器+DWORD,长度变为了5个字节。
posted @ 2011-01-06 12:48 Meiosis 阅读(450) | 评论 (0)编辑 收藏