2012年5月17日星期四

linux 程序调试

昨天调一个很简单的程序,就是从一个数据库拉取数据放到另一个数据库,谁知道一直出现 Segmentation Fault 的错误,加了printf打印,发现在mysql.close()的时候出现的错误。心里一凉,不会运气这么背吧,碰到mysql的bug?遂google之,然而还是没有找到合理的解释。只有自己调试看看了,怎么调试呢?以前做路由器的时候,也就是printf来打印,如果严重的话内核会打印堆栈,然后track之,就可以定位了。在linux下?晕了。
然后在网上搜索了半天,找到一篇用gdb调试的文章,简而言之就是编译是加-g选项,然后用gdb ./test 来调试,试了一下,确实是在mysql clsoe的时候,调用free_root的时候,在my_alloc.c里面出现错误,但是居然提示找不到my_alloc.c,叉叉啊。
冷静的想了一下,应该不会是mysql的错误,要不之前的代码岂不是问题很多。接下来采用屏蔽代码的办法,发现确实是一段代码对内存操作存在问题,由于是老代码,当时看了有疑问,但是想如果出问题的话早就有问题了,就没多想。
上代码:
01 while ((row = mysql_fetch_row(res)) != NULL)
02 {
03      k++;
04      pColLen = mysql_fetch_lengths(res);
05
06      if(NULL != row && NULL != pColLen)
07      {
08          for(int i=0; i < num_fields; i++)
09          {
10              memset(aryColValue, 0, 1024);
11              if (pColLen[i] > 1024)
12              {
13                  printf("Error:%d\r\n",pColLen[i]);
14                  printf("Error:%s\r\n",row[i]);
15              }
16              memmove(aryColValue, row[i], pColLen[i]);
17              if(utf8Flag==1)
18              {
19                  strFieldValue = Utf8ToGbk(aryColValue);
20              }
21              else
22              {
23                  strFieldValue = aryColValue;
24              }
25              if(!tmpresult.insert(std::map<std::string, std::string>::value_type(fields[i].name, strFieldValue)).second)
26              {
27                  dblog.WriteLog( "Error:tmpresult.insert(%s)失败\n",strFieldValue.c_str());
28              }
29          }
30          result.push_back(tmpresult);
31          tmpresult.clear();
32      }
33 }
memset(aryColValue, 0, 1024);
memmove(aryColValue, row[i], pColLen[i]);
这两句真是坑爹啊,aryColValue只有1024个字节,但是pCollen表示每个字段的长度,很有可能超过1024字节的,而且我看了数据库里面相关字段,是mediumtext类型,最大长度2的24次方-1个字节。这代码,无语了。而且看了其他一些代码,也是有最多1024*5个字节,这太乱来了吧。就是这段代码,直接导致内存操作越界了。
修改为tmpresult[fields[i].name] = row[i];tmpresult是一个map<string,string>,string长度至少是32位的,够用了。

我发现这老代码真是不可相信啊,各种乱来。预期后续可能还会碰到不少问题,这样看了我还要搞不少时间啊。

2012年5月4日星期五

手机连接笔记本热点上网的问题

步骤很简单:
1.在笔记本新建一个无线临时网络,加密方式要选wep。然后设置网络名和密码就可以了。
2.通常系统会默认把已有的网络连接设为共享,按理说这样就可以了。手机搜索wifi连上就可以了。
不过今天一直不行,现象就是在itouch上面看,分配到的ip地址一直是169。。。。,也不能上网。然后把本地的有线网络连接断开共享,重新设置连接共享就可以了,在itouch上面看分配到的ip就是192.168。。。。。,也可以上网了。

2012年5月1日星期二

blogger一个让我不爽的地方

想看看他人的博客,居然都找不到推荐的地方。
最后在“概述”里面,右下角的一个咔咔地方有一个最近值得关注的博客,这才找到地方了http://blogsofnote.blogspot.com/

2012年4月29日星期日

SecureCRT复制中文出来是乱码的解决办法

公司的跳板机的SecureCRT版本太老且没做特别设置,导致我今天从sql语句的结果复制中文时老是乱码。网上搜了一下,改了两个地方就ok了。
1.Font里面改了一下字体和编码,字体用Fixedsys, 编码gb2312
2.外面的字符编码改成了none
这下就ok了。

[转]i9100g搜索不到笔记本建立热点wifi的解决办法

在机锋网上面瞎逛兼等待ICS4.0的官方升级,发现一个帖子说的是i9100g搜索不了笔记本建立的wifi热点的办法。记录一下吧。另外一个帖子也说貌似是android不支持点对点的连接。我去,android还是有些毛病啊,没有ios成熟和稳定。


[教程] 关于i9100g搜索不到笔记本建立热点wifi的解决办法


针对部分机油还不知道,发一下教程

先把手机ROOT了,然后再装个RE管理器,把我发的压缩包解压得到wpa_supplicant文件(先备份哦),用RE管理器拷到system/bin/下,覆盖原文件,就可以搜到了,搜到了输完密码,需要把手机的WIFI关一下再开就可以连上了

2012年4月24日星期二

cgi接口运行出现500错误

    在做一个cgi接口时,编译ok了,但是调用这个接口时始终显示500错误,请同事看说是程序用的mysql的库有问题(这怎么看出来的?以后研究一下),但是在编译程序的时候包含了正确的mysql库了,没搞懂。然后给同事看了一下,他把我的makefile改了一下:
g++ -Wl,-rpath,./lib a.h a.cpp b.cpp -o a$(INCLUDE) $(LIB)
加了-Wl,-rpath参数,然后就可以了。高啊。

在网上查了一下:
1)-Wl,<选项> 将逗号分隔的 <选项> 传递给链接器
2)-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路径查找库,避免了使用LD_LIBRARY_PATH环境变量查找
加了这两个参数后,应该是把mysql的库编译到程序里面了。

对gcc的编译,我还处于初级阶段,只懂得皮毛,以后有机会学习一下。

另外cgi接口运行出现500错误的原因还有一种就是没有输出html头部信息,只要把头部信息加上就可以了。(printf("Content-type: text/html;charset=utf-8\n\n"); )
也有人说权限问题可能会造成500错误。

3,4月出差小结

    来深圳出差一个多月,独自和另外一个部门打交道,虽然有不少时间花在交流,等待上面,不过一个人干活的好处就是在压力下面可以更快的学习。
    这次被放到游戏部门,说起来简单是做两个接口的工作,但是里面的小细节还是很多的。首先就是看代码,在只懂一点流程的情况下,硬生生的看了两个版本的代码,还好之前做路由器时看代码已经被练成即使不懂具体技术,模块,也可以按逻辑把代码的业务流程搞清楚,这样就活生生的把程序的流程搞清楚了。
    在具体技术上面也学到不少东西,虽然没有很系统的知识,但是就是看代码加问人,学到不少新东西:
1.数据库mysql,之前除了select语句之外,基本都忘了sql的知识了,这次搞了一下数据库,熟悉了一些基本的操作命令和sql语句,应付工作应该是够了。
2.linux下面使用c++和mysql打交道,这点知识完全是看别人的代码学到的,以后可以用上。
3.gcc,shell编程。gcc只搞过一点点,这次要编译几个文件都还查了半天,后续具体研究一下。shell编程以前也是没搞过,这次也是看代码加上网查,学到不少。
这次出差回去的话有几个东西要搞一搞,一个就是把自己的开发环境搞好,话说笔记本上面跑虚拟机真是慢啊,很想入手一个超级本,ssd跑虚拟机绝对爽翻了。另外一个就是根据这次出差的情况把gcc,shell编程看看。前段时间还是没规划好,时间浪费了很多啊。