COMMENTS

细心的写代码很重要

一个很简单的说法早都知道,那就是内存泄漏,或者说访问了未申请的内存空间会产生不可预料的错误。
之前就遇到一个问题,在我机器上编译的二进制程序运行出错,除了在我的机器以外,在同事的机器上运行一样出错。意外的是同事拿走我的源码在他机器上编译后的二进制程序,除了在他自己的机器上运行正常,在我机器上运行同样不会出错。
最后是找啊找,找啊找。发现了一个用来存储一条SQL语句的char型数组被声明成了128字节长,事实上这条SQL语句在某些情况下会超出128字节,这样的错误找起来真是累人,改大了一点后,一切正常了。
不幸的是就在上周,又遇到了类似的错误,还是费了半天劲,发现是一个两位数的负数被放到了一个char型的数组中,而这个数组只有2字节长,天那,如果吸取了上次的教训,就不用花好几个小时来找这样让人头疼的错误了。话说回来,在一个char型数组中放置一个数字,还是个负数,用起来还要进行转换,岂不是很麻烦。 哦,忘了,是因为要用char型而从int转换过去的。无语。
为什么不可预料的错误在某个机器上100%出错,而在另一个机器上100%没错(虽然我没尝试100次),也行这只能用不可预料来解释了。

细心一点吧,这样的问题应该在写的时候就应该避免,编译器不会帮我们这个忙。

利用sudo为PHP批特权

有时候需要在web上执行一些特殊的终端命令。例如ps,为了在web上显示出当前的进程列表,因为我经常做一些系统方面的编程,所以有时候就不得不做这些高危险性的事情。用下边的方法就可以允许php用exec,system等函数来执行这些终端命令。
键入命令visudo,打开sudoers文件,编辑该文件
注释掉Defaults requiretty一行,并在文件末尾追加Apache ALL=NOPASSWD:/bin/ps
这样,在php中就可以用类似这样的语句去执行ps命令exec(”/usr/bin/sudo /bin/ps -e”); ,当然,ps的参数可以随意指定,和在终端下使用一样。需要注意的是这里使用的是apache服务器,不同的web服务器该方法应该不能混用。
不允许php来执行的命令有很多,比如chkconfig,想开启或关闭一个服务,这些只有root才能做的事情,普通用户都是没有权限的,跟何况要php去做。所以同样的会带来安全问题,总之慎用就好。

记之,与大家分享,以备后用。

触动

刚才在一个朋友的blog上看到的一段视频,让我心底一动
想起曾经因为给了一毛钱而被小女孩抱着腿不放,而肯定是被指使的
也想起在大学时给一个老婆婆5块钱,在冬天,风很大很冷的一天
现在呢?我还会吗?
还是我根本就没用眼去看看他是不是如视频中的一样

带有#和##符号的函数式宏展开步骤

在函数式宏定义中,#运算符用于创建字符串,#运算符后面应该跟一个形参(中间可以有空格或Tab),s将被作为一个字符串替换,并且s中的多个空格或tab将被替换为一个空格。
#define STR(s) # s
STR(hello world)
预处理后变为”hello world” 。
##运算符把前后两个预处理Token连接成一个预处理Token,和#运算符不同,##运算符不仅限于函数式宏定义,变量式宏定义也可以用。
先列出一个例子,当然这不是一段可执行的程序,甚至编译不了,只是为了说明宏展开的步骤问题,事实上这样的宏定义很多地方都能见到。

#define _sh(x) p_f(”n”,#x,”=%d, or %d\n”,n##x,alt[x])
#define sh(x) _sh(x)
#define NA 26
_sh(NA)
sh(NA)

可能发现第二行的定义有些多余,但结果却是截然不同的。
使用cpp命令做一下预处理就可以看到_sh(NA)和sh(NA)展开的不同,以下为展开结果。

p_f(”n”,”NA”,”=%d, or %d\n”,nNA,alt[26])
p_f(”n”,”26″,”=%d, or %d\n”,n26,alt[26])

下边分别说一下_sh(NA)和sh(NA)的展开步骤

_sh(NA)展开的步骤如下:
1.#x要替换成”NA”。
2.n##x要替换成nNA。
3.除了带#和##运算符的参数之外,其它参数在替换之前要对实参本身做充分的展开,所以应该先把NA展开成26再替换到alt[x]中x的位置。换言之,带有#和##的不会再进行二次替换。
4.现在展开成了p_f(”n” “NA” “=%d, or %d\n”,nNA,alt[26]),所有参数都替换完了,这时编译器会再扫描一遍,再找出可以展开的宏定义来展开,假设NA或alt是变量式宏定义,这时会进一步展开,但经#或##替换的除外,所以”NA”并没有成为”26“,nNA也没有被替换为n26。

sh(NA)展开的步骤如下:
1.用_sh(NA)替换sh(NA),并扫描,发现NA可以再展开,展开为_sh(26)
2. 展开_sh(26)为p_f(”n”,”26″,”=%d, or %d\n”,n26,alt[26])

所以,当期望宏替换为变量式宏的值而不是这个宏名,并且有#或者##在使用时,就要格外注意了,需要再加一条看似废话的宏定义。

另外,关于带有可变参数的函数在宏定义时,除了可以使用__VA_ARGS__来替代可变参数外,也可以使用##来连接。如下的两个宏定义是类似的

#define vprint(fmt, …) log_z(__FILE__,__LINE__,fmt,__VA_ARGS__)
#define vprint(fmt,args…) log_z(__FILE__,__LINE__,fmt,## args)

这个宏常用在日志函数中,调用vprint函数就加入了文件名和行号,方便debug,也可以加入__DATE__,__TIME__等等预定义变量,log_z函数实现如下

void log_z(char *fn,int ln,const char *fmt, …)
{
va_list ap;
char buf[4096];
va_start(ap,fmt);
vsnprintf(buf,4096,fmt,ap);
printf(”[%s %d]“,fn,ln);
printf(buf);
printf(”\n”);
}

另一个更加简单有效的增加行号的做法是这样定义的

#define vprint(fmt,args…) printf(”[%s %d]“fmt,__FILE__,__LINE__,##args)

这个让你想起了什么

看到这个视频,一下子想到了N久前,从小玩游戏的你一定不会感到陌生
上上下下左左右右ABAB…. 这个还记得么

秀一下我的奥金鱼竿

今天天气真不错,阳光明媚,蓝蓝的天上飘着几朵白云。
又到了一周一次的钓鱼比赛了,上周的比赛让老婆给搅黄了,比较郁闷。其实上上周就拿了冠军,得到了鱼竿,一直比较忙,都没纪念一下,今天补上,但愿今天如愿以偿的再拿一次冠军,便了结了钓鱼梦想了。
尽管在学校的时候已经拿到过一次冠军,时隔几年后再一次拿到冠军,依旧是那么心潮澎湃。回想在学校的时候,比赛的人那叫一个多,还经常有敌对阵营的骚扰,辛辛苦苦比赛了两个月才拿到冠军,最郁闷的一次是已经炉石并且把任务都点开了,让别人抢先我0.0**秒交了任务,无比郁闷一次比赛,成为了我钓鱼史上最悲剧的一件事情。
无图无真相,看看我的卫冕冠军吧! fishing-rod

吃饭去喽,天气好,心情好!

成功激活windows 7

起初装上win7的一段时间,找了很多个激活工具,统统无法激活,后来索性不管了,不就30天续约一次么,据说可以和win7约好多次,大概可以试用一年,也就这么用着了。无意中浏览新闻看到某某记者的盗版win7评测,好家伙,真受用。让我找遍大坛小站的激活问题,最后竟是XX记者提供了这么NB的方法。在此表示感谢!

如果正在睁着大眼睛的您也需要,请看关键词:win7 神Key 电话激活。请自行排列组合关键词并baidu,google,一定能得到您想要的。
关键词很神,功能更神,相信我!

淡定

不如意的事情总是挥走一件又来一件,总是让人不得消停似乎是注定的。
可能引以为傲的成果在别人眼里就会不值一提,被批的体无全肤,临了除了一堆的改进意见还要外加几项新的东西,甚至全盘否定,扔掉重来。渴望被人赞赏恰恰又只站在了自己的角度,最终只能是个花瓶孤芳自赏,这也许就是单纯的技术人员的思维,应该怎样呢?
同样渴望被人同情理解安慰,恰恰又是在不适当的时候,一句嗓门大点的话就成了迅速燃烧的导火索。
难道我的初衷有错吗?也许。为什么自己不如意的事情还要转嫁他人,为什么又不能找一个更切切的方式。寄希望于他人总是不明智的做法,淡定,让自己来消化掉这些烦恼,烦躁的心情只会伤人伤己。
我们需要别人,更需要自己,如何站在一个位置使之保持平衡,我想该是认真思索而去实现的。

淡定这个词出自哪里,在我的游戏中是很多人的一句口头禅,现实中却没有用过

博客终于又回来了

不自己搞博客真不知道网络被如此的监管着,一直认为网络挺开放,挺自由的,直到一周前无法访问,然后就看到了机房的通知,被上级查封了。

不管怎么说,现在又回来了,毫发无损,高兴。

动态库静态库的编译和使用方法学习记录

本文参考资料:《Linux编程一站式学习》 版权 © 2008, 2009 宋劲杉, 北京亚嵌教育研究中心
部分内容摘自此文

有时候需要把一组代码编译成一个库,这个库在很多项目中都要用到,例如libc就是这样一个库,我们在不同的程序中都会用到libc中的库函数(例如printf),也会用到libc中的变量。
学习中用到的一个简单的小程序,程序将字符a,b,c压入堆栈stack[512],随后再倒序输出,打印出cba。为了使用到的gcc命令更具有意义,特意将程序分开在了几个C文件中,最后将几个.o文件链接为可执行文件。
stack.c

char stack[512];
int top = -1;

pop.c

extern int top;
extern char stack[512];
char pop(void)
{
return stack[top--];
}

push.c

extern int top;
extern char stack[512];
void push(char c)
{
stack[++top]=c;
}

继续阅读