博客首页
注册
建议与交流
排行榜
加入友情链接
推荐
投诉
搜索:
帮助
超越无限的博客
做好你想做的--其它的都不重要。。。
lidaibin.cublog.cn
管理博客
发表文章
留言
收藏夹
· 朋友
博客圈
音乐
相册
· 屏幕截图
文章
· linux
}
· gentoo
· asm
· c/c++
· python
· 生活随笔
首页
关于作者
姓名:李代斌 职业:程序员 年龄:27 位置:陕西西安 个性介绍:心比天高
||
<<
>>
||
我的分类
文章列表 - c/c++
关于inotify
<p>inotify是什么?用它能干些什么?这个问题我们还是首先从内核的文档开始吧-- Documentation/filesystems/inotify.txt(说点题外话,内核文档虽然是没有任何格式的txt文档,给人的感觉却非常 好,而且作者总是以最精炼的语言清楚地描述了相关的内容): a powerful yet simple file change notification system,通俗点说它是一个内核用于通知用户空间客户程序文件系统变化的系统,并且它是powerful yet simple的。<br><br>inotify的用户接口原型主要有以下3个:<br>初始化:int inotify_init(void);<br>添加监视对象:int inotify_add_watch(int fd, const char *path, uint32_t mask);<br>删除监视对象:int inotify_rm_watch(int fd, uint32_t wd);<br><br>内核文档里对于inotify_rm_watch的用户接口原型描述似乎有点问题,第2个参数写成了mask,实际上它应该是inotify_add_watch返回的watch descriptor。<br><br>根据文档描述可以看出,inotify使用大概分为以下几个步骤:<br>1、int fd = inotify_init(); 初始化inotify实例。<br>2、 int wd = inotify_add_watch(fd, path, mask); 添加监视对象,这里的mask是一个或多个事件的位标记集合,具体的事件定义可参考(linux/inotify.h)或者 (sys/inotify.h),前者为linux内核头文件,后者为glibc提供的头文件。<br>3、size_t len = read(fd, buf, BUF_LEN); 读取事件数据,buf应是一个指向inotify_event结构数组的指针。不过要注意的是inotify_event的name成员长度是可变的,这个问题后面再解释。<br>4、已经存在的监视对象可通过int ret = inotify_rm_watch(fd, wd);来删除。<br><br>下面我们来看一个示例:<br></p><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdio.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><unistd.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/select.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><errno.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/inotify.h></font><br><br><font color="#fa8072">static</font> <font color="#9acd32"><b>void</b></font><br><font color="#7fffd4"><b>_inotify_event_handler</b></font>(<font color="#fa8072">struct</font> <font color="#9acd32"><b>inotify_event</b></font> *<font color="#7fffd4"><b>event</b></font>)<br>{<br> printf(<font color="#ffa07a">"event->mask: 0x%08x\n"</font>, event->mask);<br> printf(<font color="#ffa07a">"event->name: %s\n"</font>, event->name);<br>}<br><br><font color="#9acd32"><b>int</b></font><br><font color="#7fffd4"><b>main</b></font>(<font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>argc</b></font>, <font color="#9acd32"><b>char</b></font> **<font color="#7fffd4"><b>argv</b></font>)<br>{<br> <font color="#fa8072">if</font> (argc != 2) {<br> printf(<font color="#ffa07a">"Usage: %s <file/dir>\n"</font>, argv[0]);<br> <font color="#fa8072">return</font> -1;<br> }<br><br> <font color="#9acd32"><b>unsigned</b></font> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>buf</b></font>[1024] = {0};<br> <font color="#fa8072">struct</font> <font color="#9acd32"><b>inotify_event</b></font> *<font color="#7fffd4"><b>event</b></font> = {0};<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>fd</b></font> = inotify_init();<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>wd</b></font> = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS);<br><br> <font color="#fa8072">for</font> (;;) {<br> <font color="#9acd32"><b>fd_set</b></font> <font color="#7fffd4"><b>fds</b></font>;<br> FD_ZERO(&fds);<br> FD_SET(fd, &fds);<br> <font color="#fa8072">if</font> (select(fd + 1, &fds, <font color="#7fffd4">NULL</font>, <font color="#7fffd4">NULL</font>, <font color="#7fffd4">NULL</font>) > 0) {<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>len</b></font>, <font color="#7fffd4"><b>index</b></font> = 0;<br> <font color="#fa8072">while</font> (((len = read(fd, &buf, <font color="#fa8072">sizeof</font>(buf))) < 0) && (errno == EINTR));<br> <font color="#fa8072">while</font> (index < len) {<br> event = (<font color="#fa8072">struct</font> <font color="#9acd32"><b>inotify_event</b></font> *)(buf + index);<br> _inotify_event_handler(event);<br> index += <font color="#fa8072">sizeof</font>(<font color="#fa8072">struct</font> <font color="#9acd32"><b>inotify_event</b></font>) + event->len;<br> }<br> }<br> }<br><br> inotify_rm_watch(fd, wd);<br><br> <font color="#fa8072">return</font> 0;<br>}<br></pre><br><br>由 以上代码可以看出inotify_init返回的file descriptor是可以用select或者poll进行I/O复用的。由于inotify_event长度是可变的,因此在读取 inotify_event数组内容的时候需要动态计算下一个事件数据的偏移量(index += sizeof(struct inotify_event) + event->len),len成员即name成员的长度。<br><br>在实际测试过程中,通过运行以上的 测试程序监视一个文件,还遇到过两个奇怪的现象:用vim编辑那个被监视的文件,修改并保存,触发的是IN_DELETE_SELF和 IN_MOVE_SELF事件而不是我们所期望的IN_MODIFY事件;再次修改并保存的时候不再有任何事件发生。希望能给看官一个教训,其实这是由于 vim的工作机制引起的,vim会先将源文件复制为另一个文件,然后在另一文件基础上编辑(一般后缀名为swp),保存的时候再将这个文件覆盖源文件,因 此会出现上述的第一个现象,第二个现象是因为原来的文件已经被后来的新文件代替,因此监视对象所监视的文件已经不存在了,所以自然不会产生任何事件。<br><br>另外,内核文档第四部分介绍了inotify的背景以及设计思路,不可不看:<br><br>Q: What is the design decision behind not tying the watch to the open fd of<br> the watched object?<br><br>A: Watches are associated with an open inotify device, not an open file.<br> This solves the primary problem with dnotify: keeping the file open pins<br> the file and thus, worse, pins the mount. Dnotify is therefore infeasible<br> for use on a desktop system with removable media as the media cannot be<br> unmounted. Watching a file should not require that it be open.<br><br>Q: What is the design decision behind using an-fd-per-instance as opposed to<br> an fd-per-watch?<br><br>A: An fd-per-watch quickly consumes more file descriptors than are allowed,<br> more fd's than are feasible to manage, and more fd's than are optimally<br> select()-able. Yes, root can bump the per-process fd limit and yes, users<br> can use epoll, but requiring both is a silly and extraneous requirement.<br> A watch consumes less memory than an open file, separating the number<br> spaces is thus sensible. The current design is what user-space developers<br> want: Users initialize inotify, once, and add n watches, requiring but one<br> fd and no twiddling with fd limits. Initializing an inotify instance two<br> thousand times is silly. If we can implement user-space's preferences <br> cleanly--and we can, the idr layer makes stuff like this trivial--then we <br> should.<br><br> There are other good arguments. With a single fd, there is a single<br> item to block on, which is mapped to a single queue of events. The single<br> fd returns all watch events and also any potential out-of-band data. If<br> every fd was a separate watch,<br><br> - There would be no way to get event ordering. Events on file foo and<br> file bar would pop poll() on both fd's, but there would be no way to tell<br> which happened first. A single queue trivially gives you ordering. Such<br> ordering is crucial to existing applications such as Beagle. Imagine<br> "mv a b ; mv b a" events without ordering.<br><br> - We'd have to maintain n fd's and n internal queues with state,<br> versus just one. It is a lot messier in the kernel. A single, linear<br> queue is the data structure that makes sense.<br><br> - User-space developers prefer the current API. The Beagle guys, for<br> example, love it. Trust me, I asked. It is not a surprise: Who'd want<br> to manage and block on 1000 fd's via select?<br><br> - No way to get out of band data.<br><br> - 1024 is still too low. ;-)<br><br> When you talk about designing a file change notification system that<br> scales to 1000s of directories, juggling 1000s of fd's just does not seem<br> the right interface. It is too heavy.<br><br> Additionally, it _is_ possible to more than one instance and<br> juggle more than one queue and thus more than one associated fd. There<br> need not be a one-fd-per-process mapping; it is one-fd-per-queue and a<br> process can easily want more than one queue.<br><br>Q: Why the system call approach?<br><br>A: The poor user-space interface is the second biggest problem with dnotify.<br> Signals are a terrible, terrible interface for file notification. Or for<br> anything, for that matter. The ideal solution, from all perspectives, is a<br> file descriptor-based one that allows basic file I/O and poll/select.<br> Obtaining the fd and managing the watches could have been done either via a<br> device file or a family of new system calls. We decided to implement a<br> family of system calls because that is the preferred approach for new kernel<br> interfaces. The only real difference was whether we wanted to use open(2)<br> and ioctl(2) or a couple of new system calls. System calls beat ioctls.
查看全文
发表于:2007-06-21 ┆
阅读(752)
┆
评论(0)
rs422在linux下跟我开了个玩笑
<p>很久没有更新blog了,就跟抽烟一样,如果长时间不抽的话也就不想抽了,看来这是一个不好的现象,不过长时间的沉默也说明了自己这段时间在技术上没有什么积累。罢了,今天的blog就记录这段时间来比较郁闷的事情。<br><br>这 个项目的开发就像当年初中的长跑一样,前几圈劲头十足信心满怀,接下来的情况我想大部分人跟我一样,慢慢地感觉有点累,再后来压力越来越大,越来越感觉大 脑缺氧呼吸困难,到后来已经身心疲累。人这一生从出生开始就背负了责任,要么为责任活着要么超越责任为理想活着,所以有人活得辛苦而无趣,有人轻松而超 然。有点跑题了,还是说一下前几天遇到的技术问题。<br><br>客户方有一外部设备是N年前购买的,一直用于原来的系统中,这次需要在本项目中使用此 外设,关于这个外设的文档早已缺失,唯一可以参考的就是一个windows下的动态链接库源代码(不过这也是最重要的参考资料,候大侠一本书上不是也说 “源码面前了无秘密”嘛),于是参考此代码写了一个windows下的测试程序很顺利地测试通过,测试代码如下:<br></p><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#fa8072">#include</font> <font color="#ffa07a"><windows.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdio.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdlib.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><string.h></font><br><br><font color="#9acd32"><b>int</b></font><br><font color="#7fffd4"><b>main</b></font>(<font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>argc</b></font>, <font color="#9acd32"><b>char</b></font> **<font color="#7fffd4"><b>argv</b></font>)<br>{<br> <font color="#9acd32"><b>HANDLE</b></font> <font color="#7fffd4"><b>h_com</b></font>;<br> <font color="#9acd32"><b>unsigned</b></font> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>addr</b></font> = 0x01;<br> <font color="#9acd32"><b>unsigned</b></font> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>buf</b></font>[10];<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>i</b></font>;<br> <font color="#9acd32"><b>DCB</b></font> <font color="#7fffd4"><b>dcb</b></font>;<br> <font color="#9acd32"><b>COMMTIMEOUTS</b></font> <font color="#7fffd4"><b>timeouts</b></font>;<br> <font color="#9acd32"><b>DWORD</b></font> <font color="#7fffd4"><b>n</b></font>;<br><br> <font color="#fa8072">if</font> (argc != 2) {<br> printf(<font color="#ffa07a">"%s <comdev>\n"</font>, argv[0]);<br> <font color="#fa8072">return</font> -1;<br> }<br><br> h_com = CreateFile(argv[1], GENERIC_READ | GENERIC_WRITE,<br> 0, <font color="#7fffd4">NULL</font>, OPEN_EXISTING, 0, <font color="#7fffd4">NULL</font>);<br> <font color="#fa8072">if</font> (h_com == INVALID_HANDLE_VALUE) {<br> printf(<font color="#ffa07a">"Initialize COM device failed\n"</font>);<br> <font color="#fa8072">return</font> -1;<br> }<br><br> GetCommState(h_com, &dcb);<br> dcb.BaudRate = 9600;<br> dcb.ByteSize = 8;<br> dcb.Parity = MARKPARITY;<br> dcb.StopBits = ONESTOPBIT;<br> SetCommState(h_com, &dcb);<br><br> GetCommTimeouts(h_com, &timeouts);<br> timeouts.ReadTotalTimeoutConstant = 10;<br> SetCommTimeouts(h_com, &timeouts);<br><br> WriteFile(h_com, &addr, <font color="#fa8072">sizeof</font>(addr), &n, <font color="#7fffd4">NULL</font>);<br><br> Sleep(1);<br> dcb.Parity = SPACEPARITY;<br> SetCommState(h_com, &dcb);<br> memcpy(buf, <font color="#ffa07a">"\x02\x85\x83\04"</font>, 4);<br> WriteFile(h_com, buf, 4, &n, <font color="#7fffd4">NULL</font>);<br><br> Sleep(2);<br> ReadFile(h_com, buf, <font color="#fa8072">sizeof</font>(buf), &n, <font color="#7fffd4">NULL</font>);<br> printf(<font color="#ffa07a">"read %d bytes\n"</font>, n);<br><br> <font color="#fa8072">for</font> (i = 0; i < n; ++i)<br> printf(<font color="#ffa07a">"%02x "</font>, buf[i]);<br> printf(<font color="#ffa07a">"\n"</font>);<br><br> <font color="#fa8072">return</font> 0;<br>}<br></pre><br>由此代码可以看出通信过程大概是这样的:将串口设置为8M1发送地址,然后将串口设置更改为8S1发送请求数据,再然后接收数据,看起来还是很简单的。接下来很快地写好了linux下的测试程序,源代码如下:<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdio.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdlib.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><string.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><unistd.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/types.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/stat.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/ioctl.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><fcntl.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><termios.h></font><br><br><font color="#9acd32"><b>int</b></font><br><font color="#7fffd4"><b>main</b></font>(<font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>argc</b></font>, <font color="#9acd32"><b>char</b></font> **<font color="#7fffd4"><b>argv</b></font>)<br>{<br> <font color="#fa8072">if</font> (argc != 2) {<br> printf(<font color="#ffa07a">"Usage: %s <comdev>\n"</font>, argv[0]);<br> <font color="#fa8072">return</font> -1;<br> }<br><br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>fd</b></font> = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);<br> <font color="#fa8072">if</font> (fd == -1) {<br> printf(<font color="#ffa07a">"Initialize COM device failed.\n"</font>);<br> <font color="#fa8072">return</font> -1;<br> }<br><br> <font color="#fa8072">struct</font> <font color="#9acd32"><b>termios</b></font> <font color="#7fffd4"><b>options</b></font>;<br> <font color="#fa8072">if</font> (tcgetattr(fd, &options) == -1)<br> <font color="#fa8072">return</font> -1;<br><br> cfsetispeed(&options, B9600);<br> cfsetospeed(&options, B9600);<br><br> options.c_cflag &= ~CSIZE;<br> options.c_cflag |= CS8 | CLOCAL | CREAD | CMSPAR | PARODD;<br> options.c_cflag &= CSTOPB;<br> options.c_iflag |= INPCK;<br> options.c_iflag &= ~(IXON | IXOFF | IXANY);<br> options.c_oflag &= ~OPOST;<br> options.c_lflag &= ~(ECHO | ECHOE | ICANON | ISIG);<br> tcflush(fd, TCIFLUSH);<br> printf(<font color="#ffa07a">"tcsetattr result: %d\n"</font>, tcsetattr(fd, TCSANOW, &options));<br><br> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>addr</b></font> = 0x01;<br> <font color="#fa8072">if</font> (write(fd, &addr, 1) == -1)<br> <font color="#fa8072">goto</font> <font color="#7fffd4">failed</font>;<br><br> usleep(1000);<br><br> options.c_cflag &= ~PARODD;<br> printf(<font color="#ffa07a">"tcsetattr result: %d\n"</font>, tcsetattr(fd, TCSADRAIN, &options));<br><br> usleep(1000);<br><br> <font color="#9acd32"><b>unsigned</b></font> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>buf</b></font>[10];<br> memcpy(buf, <font color="#ffa07a">"\x02\x85\x83\x04"</font>, 4);<br><br> <font color="#fa8072">if</font> (write(fd, buf, 4) == -1)<br> <font color="#fa8072">goto</font> <font color="#7fffd4">failed</font>;<br><br> usleep(10000);<br><br> <font color="#9acd32"><b>ssize_t</b></font> <font color="#7fffd4"><b>read_n</b></font>;<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>i</b></font>;<br> read_n = read(fd, buf, <font color="#fa8072">sizeof</font>(buf));<br> printf(<font color="#ffa07a">"result: %d\n"</font>, read_n);<br> <font color="#fa8072">for</font> (i = 0; i < read_n; ++i)<br> printf(<font color="#ffa07a">"%02X "</font>, buf[i]);<br> printf(<font color="#ffa07a">"\n"</font>);<br><br> close(fd);<br> <font color="#fa8072">return</font> 0;<br><br> <font color="#7fffd4">failed</font>:<br> close(fd);<br> <font color="#fa8072">return</font> -1;<br>}<br></pre><br>虽 然Mark Parity和Space Parity在Posix中并未定义,但是在linux下通过CMSPAR仍然可以实现,<a href="http://kjell.haxx.se/man/man.cgi?page=tcsetattr&section=3" target="_blank">tcsetattr的man pages</a><a href="http://www.hmug.org/man/3/tcsetattr.php" target="_blank"></a>可以看到对CMSPAR的描述,可是反复尝试仍然有问题,后来一个完全不懂linux开发的同事问了我设置串口各行代码的意思,并通过 tcsetattr的man pages,一个一个地组合这些标记,居然成功了!结果出人意料,且看如下代码:<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdio.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdlib.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><string.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><unistd.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/types.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/stat.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><sys/ioctl.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><fcntl.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><termios.h></font><br><br><font color="#9acd32"><b>int</b></font><br><font color="#7fffd4"><b>main</b></font>(<font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>argc</b></font>, <font color="#9acd32"><b>char</b></font> **<font color="#7fffd4"><b>argv</b></font>)<br>{<br> <font color="#fa8072">if</font> (argc != 2) {<br> printf(<font color="#ffa07a">"Usage: %s <comdev>\n"</font>, argv[0]);<br> <font color="#fa8072">return</font> -1;<br> }<br><br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>fd</b></font> = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);<br> <font color="#fa8072">if</font> (fd == -1) {<br> printf(<font color="#ffa07a">"Initialize COM device failed.\n"</font>);<br> <font color="#fa8072">return</font> -1;<br> }<br><br> <font color="#fa8072">struct</font> <font color="#9acd32"><b>termios</b></font> <font color="#7fffd4"><b>options</b></font>;<br><br> memset(&options, 0, <font color="#fa8072">sizeof</font>(options));<br><br> cfsetispeed(&options, B9600);<br> cfsetospeed(&options, B9600);<br><br> options.c_cflag = CS8 | CLOCAL | CREAD | CSTOPB | CMSPAR;<br> options.c_iflag = INPCK;<br> options.c_oflag = 0;<br> options.c_lflag = 0;<br> tcflush(fd, TCIFLUSH);<br> printf(<font color="#ffa07a">"tcsetattr result: %d\n"</font>, tcsetattr(fd, TCSANOW, &options));<br><br> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>addr</b></font> = 0x01;<br> <font color="#fa8072">if</font> (write(fd, &addr, 1) == -1)<br> <font color="#fa8072">goto</font> <font color="#7fffd4">failed</font>;<br><br> usleep(1000);<br><br> options.c_cflag |= PARENB | PARODD;<br> printf(<font color="#ffa07a">"tcsetattr result: %d\n"</font>, tcsetattr(fd, TCSADRAIN, &options));<br><br> usleep(1000);<br><br> <font color="#9acd32"><b>unsigned</b></font> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>buf</b></font>[10];<br> memcpy(buf, <font color="#ffa07a">"\x02\x85\x83\x04"</font>, 4);<br><br> <font color="#fa8072">if</font> (write(fd, buf, 4) == -1)<br> <font color="#fa8072">goto</font> <font color="#7fffd4">failed</font>;<br><br> usleep(10000);<br><br> <font color="#9acd32"><b>ssize_t</b></font> <font color="#7fffd4"><b>read_n</b></font>;<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>i</b></font>;<br> read_n = read(fd, buf, <font color="#fa8072">sizeof</font>(buf));<br> printf(<font color="#ffa07a">"result: %d\n"</font>, read_n);<br> <font color="#fa8072">for</font> (i = 0; i < read_n; ++i)<br> printf(<font color="#ffa07a">"%02X "</font>, buf[i]);<br> printf(<font color="#ffa07a">"\n"</font>);<br><br> close(fd);<br> <font color="#fa8072">return</font> 0;<br><br> <font color="#7fffd4">failed</font>:<br> close(fd);<br> <font color="#fa8072">return</font> -1;<br>}<br></pre><br>想不到抛开CMSPAR不算8M1看起来是8N2,而8S1则看起来是8O2。。。
查看全文
发表于:2007-06-10 ┆
阅读(848)
┆
评论(0)
C代码中如何得到python脚本异常时的traceback信息
在软件项目的开发过程中,我们总是试图让程序能够适应更多的应用环境以及业务流程,不管你对于需求的了解如何准确,也不管你做了有多么充分的估计,但有很多情况仍然让你无法应付,比如:需求是会变化的;维护项目的人不一定都能用C/C++写出没有内存问题的代码等等。<br><br>让 软件系统能够适应更多变化的方法有很多种,高度的抽象、动态链接技术等等都是一直以来被大家采用较广的方法,那么今天我们要讨论的是脚本引擎的嵌入问题。 通常我更喜欢c代码加上python脚本引擎的结构,python的好处就不多说了。不过在C中嵌入python脚本引擎调用之后也有一些非常麻烦的地 方,比如不便于调试,因为我们的宿主应用程序必然会为python脚本wrap一些module、class、function等等,因此这带来了调试的 难度,有时候仅仅依赖print是一件非常低效的事,那么我们如何得到python脚本在异常时的traceback情况呢?比如代码出现异常到底是在哪 个脚本文件中,到底是哪行代码出了问题?错误又是什么呢?我们先来看看下面的函数:<br><br><pre style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><font color="#fa8072">#include</font> <font color="#ffa07a"><Python.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><compile.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><frameobject.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><traceback.h></font><br><br><font color="#9acd32"><b>void</b></font><br><font color="#7fffd4"><b>process_python_exception</b></font>(<font color="#9acd32"><b>void</b></font>)<br>{<br> <font color="#9acd32"><b>char</b></font> <font color="#7fffd4"><b>buf</b></font>[512], *<font color="#7fffd4"><b>buf_p</b></font> = buf;<br> <font color="#9acd32"><b>PyObject</b></font> *<font color="#7fffd4"><b>type_obj</b></font>, *<font color="#7fffd4"><b>value_obj</b></font>, *<font color="#7fffd4"><b>traceback_obj</b></font>;<br> PyErr_Fetch(&type_obj, &value_obj, &traceback_obj);<br> <font color="#fa8072">if</font> (value_obj == <font color="#7fffd4">NULL</font>)<br> <font color="#fa8072">return</font>;<br><br> <font color="#fa8072">if</font> (!PyString_Check(value_obj))<br> <font color="#fa8072">return</font>;<br><br> <font color="#9acd32"><b>char</b></font> *<font color="#7fffd4"><b>value</b></font> = PyString_AsString(value_obj);<br> <font color="#9acd32"><b>size_t</b></font> <font color="#7fffd4"><b>szbuf</b></font> = <font color="#fa8072">sizeof</font>(buf);<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>l</b></font>;<br> <font color="#9acd32"><b>PyCodeObject</b></font> *<font color="#7fffd4"><b>codeobj</b></font>;<br><br> l = snprintf(buf_p, szbuf, _(<font color="#ffa07a">"Error Message:\n%s"</font>), value);<br> buf_p += l;<br> szbuf -= l;<br><br> <font color="#fa8072">if</font> (traceback_obj != <font color="#7fffd4">NULL</font>) {<br> l = snprintf(buf_p, szbuf, _(<font color="#ffa07a">"\n\nTraceback:\n"</font>));<br> buf_p += l;<br> szbuf -= l;<br><br> <font color="#9acd32"><b>PyTracebackObject</b></font> *<font color="#7fffd4"><b>traceback</b></font> = (<font color="#9acd32"><b>PyTracebackObject</b></font> *)traceback_obj;<br> <font color="#fa8072">for</font> (;traceback && szbuf > 0; traceback = traceback->tb_next) {<br> codeobj = traceback->tb_frame->f_code;<br> l = snprintf(buf_p, szbuf, <font color="#ffa07a">"%s: %s(# %d)\n"</font>,<br> PyString_AsString(codeobj->co_name),<br> PyString_AsString(codeobj->co_filename),<br> traceback->tb_lineno);<br> buf_p += l;<br> szbuf -= l;<br> }<br> }<br><br> message_error_dialog_show(buf);<br><br> Py_XDECREF(type_obj);<br> Py_XDECREF(value_obj);<br> Py_XDECREF(traceback_obj);<br>}<br></pre><br>PyErr_Fetch 用来获取异常对象,并且同时可以得到traceback对象,traceback其实是一个PyTracebackObject结构体,可以在 python的头文件traceback.h中找到,PyTracebackObject其实也是一个单向链表,可以通过其tb_next成员来枚举,其 tb_frame则是一个_frame结构体,在frameobject.h头文件中可以看到,其中f_code就是我们需要的PyCodeObject 结构体,PyCodeObject中就可以得到co_name和co_filename这两个关键的描述,一个是错误信息另一个是文件名称, PyTracebackObject的tb_lineno就是出错的行号,有了这些数据我们调试还有困难吗?
查看全文
发表于:2007-04-15 ┆
阅读(766)
┆
评论(0)
GtkScrolledWindow滚动条问题
在使用GtkTreeView时,用GtkScrolledWindow来添加滚动条,但列表(或树)中的数据行在不断得更新(增加),而垂直滚动条默认情况下不能自动往下滚动,以显示最新的数据行,而是始终停在top的位置,针对此问题有什么方法可以解决呢?<br><br>每 次增加数据行之后,得到最后一行的path,需要手动调用gtk_tree_view_scroll_to_cell,滚动到最后的地方。如果不想手动 调用,可以监听 model 的 row-inserted,在该signal callback中gtk_tree_view_scroll_to_cell,如果大量迅速的增加新行的话,速度会受影响,可以跟延时结合减少 scroll的频率。
查看全文
发表于:2007-03-22 ┆
阅读(638)
┆
评论(0)
gtk+开发中的几个小经验
1、在gtk+开发过程中,我们经常需要在event handler中来访问该窗口中的某些控件的信息,通常习惯于整一大堆全局变量,其实还有更好的方式,在glib的实现中我们可以通过 g_object_set_data和g_object_get_data给一个GObject对象绑定自定义的数据及属性, g_object_set_data_full还可以在对象释放资源时通知你的回调函数来做资源释放处理,这样我们就可以给event handler传递一个窗口对象指针就行了,其它的数据及控件信息可以通过窗口对象得到我们想要的东西。<br><br>2、某些对象并未提供所有属性的 存取方法,但只要是通过GObject继承下来的对象均可采用g_object_set、g_object_set_property及 g_object_get、g_object_get_property来存取这些属性,如给TreeView中某一列的值要求居右则可以对 gtk_cell_renderer_text_new()产生的GtkCellRenderer对象调用g_object_set(renderer, "xalign", 1.0, NULL)来达到居右的效果。<br><br>3、使用g_idle_add及g_timeout_add等函数中的时候 一定要小心,由于代码延后执行,因此一定要保证其数据的生命周期,如下面的例子是我在开发一个项目应用中遇到的问题(注释掉的代码即为出现问题之后的修正 代码),传递的Python对象到代码执行的时候已经被释放掉了,因此出现了比较奇怪的现象:如果连续调用这个函数两次,结果加进去的两行信息全部都是最 后一次的数据,当然可能还会有更奇特的现象发生。<br><br><pre size="12px" style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><font style="color: rgb(250, 128, 114);">static</font> <font style="color: rgb(154, 205, 50);"><b>gboolean</b></font><br><font style="color: rgb(127, 255, 212);"><b>_etc_main_win_add_trans</b></font>(<font style="color: rgb(154, 205, 50);"><b>gpointer</b></font> <font style="color: rgb(127, 255, 212);"><b>data</b></font>)<br>{<br><font style="color: rgb(154, 205, 50);"><b> PyObject</b></font> *<font style="color: rgb(127, 255, 212);"><b>args</b></font> = data;<br><font style="color: rgb(250, 128, 114);"> if</font> (PyTuple_Size(args) != lv_columns)<br> <font style="color: rgb(250, 128, 114);"> return</font> FALSE;<br><br><font style="color: rgb(154, 205, 50);"><b> GtkWidget</b></font> *<font style="color: rgb(127, 255, 212);"><b>listview</b></font>;<br><font style="color: rgb(154, 205, 50);"><b> GtkTreeModel</b></font> *<font style="color: rgb(127, 255, 212);"><b>model</b></font>;<br><font style="color: rgb(154, 205, 50);"><b> GtkTreeIter</b></font> <font style="color: rgb(127, 255, 212);"><b>iter</b></font>;<br><font style="color: rgb(154, 205, 50);"><b> int</b></font> <font style="color: rgb(127, 255, 212);"><b>i</b></font>;<br><font style="color: rgb(154, 205, 50);"><b> GValue</b></font> <font style="color: rgb(127, 255, 212);"><b>value</b></font>;<br><font style="color: rgb(154, 205, 50);"><b> PyObject</b></font> *<font style="color: rgb(127, 255, 212);"><b>obj</b></font>;<br><br> listview = GTK_WIDGET(g_object_get_data(G_OBJECT(main_window), <font style="color: rgb(255, 160, 122);">"trans_list"</font>));<br> model = gtk_tree_view_get_model(GTK_TREE_VIEW(listview));<br> gtk_list_store_append(GTK_LIST_STORE(model), &amp;iter);<br><font style="color: rgb(250, 128, 114);"> for</font> (i = 0; i &lt; lv_columns; ++i) {<br> memset(&value, 0, <font style="color: rgb(250, 128, 114);">sizeof</font>(value));<br> g_value_init(&value, lv_types[i]);<br> obj = PyTuple_GetItem(args, i);<br> <font style="color: rgb(250, 128, 114);">switch</font>(lv_types[i]) {<br> <font style="color: rgb(250, 128, 114);">case</font> G_TYPE_INT:<br> <font style="color: rgb(250, 128, 114);">if</font> (PyInt_Check(obj))<br> g_value_set_int(&value, PyInt_AsLong(obj));<br> <font style="color: rgb(250, 128, 114);">break</font>;<br><br> <font style="color: rgb(250, 128, 114);">case</font> G_TYPE_LONG:<br> <font style="color: rgb(250, 128, 114);">if</font> (PyLong_Check(obj))<br> g_value_set_long(&value, PyLong_AsLong(obj));<br> <font style="color: rgb(250, 128, 114);">break</font>;<br><br> <font style="color: rgb(250, 128, 114);"> case</font> G_TYPE_UINT:<br> <font style="color: rgb(250, 128, 114);">if</font> (PyLong_Check(obj))<br> g_value_set_uint(&value, PyLong_AsUnsignedLong(obj));<br> <font style="color: rgb(250, 128, 114);">break</font>;<br><br> <font style="color: rgb(250, 128, 114);">case</font> G_TYPE_ULONG:<br> <font style="color: rgb(250, 128, 114);">if</font> (PyLong_Check(obj))<br> g_value_set_ulong(&value, PyLong_AsUnsignedLong(obj));<br> <font style="color: rgb(250, 128, 114);">break</font>;<br><br> <font style="color: rgb(250, 128, 114);">case</font> G_TYPE_FLOAT:<br> <font style="color: rgb(250, 128, 114);">if</font> (PyFloat_Check(obj))<br> g_value_set_float(&value, PyFloat_AsDouble(obj));<br> <font style="color: rgb(250, 128, 114);">break</font>;<br><br> <font style="color: rgb(250, 128, 114);">case</font> G_TYPE_DOUBLE:<br> <font style="color: rgb(250, 128, 114);">if</font> (PyFloat_Check(obj))<br> g_value_set_double(&value, PyFloat_AsDouble(obj));<br> <font style="color: rgb(250, 128, 114);">break</font>;<br><br> <font style="color: rgb(250, 128, 114);">default</font>:<br> <font style="color: rgb(250, 128, 114);">if</font> (PyString_Check(obj))<br> g_value_set_string(&value, PyString_AsString(obj));<br> <font style="color: rgb(250, 128, 114);">break</font>;<br> }<br> gtk_list_store_set_value(GTK_LIST_STORE(model), &amp;iter, i, &value);<br> }<br><br><font style="color: rgb(173, 216, 230);"> //</font><font style="color: rgb(173, 216, 230);">Py_XDECREF(args);<br></font> <font style="color: rgb(250, 128, 114);">return</font> FALSE;<br>}<br><br><font style="color: rgb(154, 205, 50);"><b>void</b></font><br><font style="color: rgb(127, 255, 212);"><b>etc_main_win_add_trans</b></font>(<font style="color: rgb(154, 205, 50);"><b>PyObject</b></font> *<font style="color: rgb(127, 255, 212);"><b>args</b></font>)<br>{<br><font style="color: rgb(173, 216, 230);"> //</font><font style="color: rgb(173, 216, 230);">Py_INCREF(args);<br></font> g_idle_add(_etc_main_win_add_trans, args);<br>}</pre>
查看全文
发表于:2007-03-22 ┆
阅读(686)
┆
评论(1)
程序库的autotools脚本
1、configure.ac的不同<br><pre style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79); font-size: 12px;"><font color="#008a8c">AC_INIT</font><font color="#6b59ce">()</font><br><font color="#008a8c">AM_INIT_AUTOMAKE</font><font color="#6b59ce">(</font>lclibs<font color="#6b59ce">,</font> <font color="#ff00ff">0.1</font><font color="#6b59ce">)</font><br><font color="#008a8c">AM_CONFIG_HEADER</font><font color="#6b59ce">([</font>config.h<font color="#6b59ce">])</font><br><br><font color="#0000ff"># Checks for programs.</font><br><font color="#008a8c">AC_PROG_CC</font><br><br><font color="#0000ff"># 库与应用程序不一样,需要libtool支持</font><br><font color="#0000ff"># 一般不用intltool,所以没有AC_PROG_INTLTOOL</font><br><font color="#008a8c">AC_PROG_LIBTOOL</font><br><br><font color="#0000ff"># Checks for libraries.</font><br><br><font color="#0000ff"># Checks for header files.</font><br><font color="#008a8c">AC_HEADER_STDC</font><br><font color="#008a8c">AC_CHECK_HEADERS</font><font color="#6b59ce">([</font>arpa/inet.h netdb.h netinet/<font color="#a52829"><b>in</b></font>.h stdlib.h string.h strings.h sys/socket.h unistd.h<font color="#6b59ce">])</font><br><br><font color="#0000ff"># Checks for typedefs, structures, and compiler characteristics.</font><br><font color="#008a8c">AC_C_CONST</font><br><font color="#008a8c">AC_C_INLINE</font><br><font color="#008a8c">AC_TYPE_SIZE_T</font><br><br><font color="#0000ff"># Checks for library functions.</font><br><font color="#008a8c">AC_FUNC_MALLOC</font><br><font color="#008a8c">AC_FUNC_REALLOC</font><br><font color="#008a8c">AC_CHECK_FUNCS</font><font color="#6b59ce">([</font>atexit bzero gethostbyname inet_ntoa memset socket strcasecmp strchr strdup strpbrk strspn strstr<font color="#6b59ce">])</font><br><br><font color="#008a8c">AC_OUTPUT</font><font color="#6b59ce">([</font><br>Makefile<br>src/Makefile<br><font color="#6b59ce">])</font><br><br></pre><br>2、src/Makefile.am的不同<br><pre style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79); font-size: 12px;"><font color="#a52829"><b>lib_LTLIBRARIES </b></font>= liblclibs.la<br><font color="#298a52"><b>liblclibs_la_SOURCES </b></font>= <font color="#6b59ce">\</font><br> utils.c<font color="#6b59ce">\</font><br> stack.c<font color="#6b59ce">\</font><br> sockets_wrapper.c<font color="#6b59ce">\</font><br> queue.c<font color="#6b59ce">\</font><br> packages.c<font color="#6b59ce">\</font><br> inifiles.c<font color="#6b59ce">\</font><br> hash.c<br><br><font color="#008a8c">lclibsincludedir </font>= <font color="#008a8c">$(includedir)</font>/lclibs<br><font color="#a52829"><b>lclibsinclude_HEADERS </b></font>= <font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>lclibs.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>utils.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>threads_wrapper.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>stack.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>sockets_wrapper.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>queue.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>packages.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>inifiles.h<font color="#6b59ce">\</font><br><font color="#6b59ce"> </font>hash.h</pre>
查看全文
发表于:2007-03-22 ┆
阅读(427)
┆
评论(0)
autotools实践
1、准备好目录树(一般情况下请将源码扔/src目录)<br><br>2、运行autoscan && mv configure.scan configure.ac && rm -f autoscan*<br><br>修 改configure.ac,去掉AC_INIT后面括号里的东西,增加AM_INIT_AUTOMAKE(你的包名, 包版本号),并将AC_CONFIG_HEADER改为AM_CONFIG_HEADER,删除掉AC_CONFIG_FILES,改AC_OUTPUT 为AC_OUTPUT(Makefile src/Makefile po/Makefile.in),用AC_CONFIG_FILES在automake时会报错。<br><br>3、注意加上你程序中用到的库和头文件检测语句,看起来应如下所示:<br><pre size="12px" style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><font style="color: rgb(0, 138, 140);">AC_INIT</font><font style="color: rgb(107, 89, 206);">()</font><br><font style="color: rgb(0, 138, 140);">AM_INIT_AUTOMAKE</font><font style="color: rgb(107, 89, 206);">(</font>dsrc<font style="color: rgb(107, 89, 206);">,</font> <font style="color: rgb(255, 0, 255);">0.1</font><font style="color: rgb(107, 89, 206);">)</font><br><font style="color: rgb(0, 138, 140);">AM_CONFIG_HEADER</font><font style="color: rgb(107, 89, 206);">(</font>config.h<font style="color: rgb(107, 89, 206);">)</font><br><br><font style="color: rgb(0, 0, 255);"># Checks for programs.</font><br><font style="color: rgb(0, 138, 140);">AC_PROG_CC</font><br><font style="color: rgb(0, 138, 140);">AC_PROG_INTLTOOL</font><br><br><font style="color: rgb(0, 0, 255);"># Checks for libraries.</font><br><font style="color: rgb(0, 0, 255);"># PKG_CHECK_MODULES可直接在Makefile.am中引用$(xxx_CFLAGS)和$(xxx_LIBS)</font><br><font style="color: rgb(0, 138, 140);">PKG_CHECK_MODULES</font><font style="color: rgb(107, 89, 206);">(</font>xml2<font style="color: rgb(107, 89, 206);">,</font> <font style="color: rgb(107, 89, 206);">[</font>xml2<font style="color: rgb(107, 89, 206);">])</font><br><font style="color: rgb(0, 138, 140);">PKG_CHECK_MODULES</font><font style="color: rgb(107, 89, 206);">(</font>openssl<font style="color: rgb(107, 89, 206);">,</font> <font style="color: rgb(107, 89, 206);">[</font>openssl<font style="color: rgb(107, 89, 206);">])</font><br><br><font style="color: rgb(0, 138, 140);">AC_CHECK_LIB</font><font style="color: rgb(107, 89, 206);">([</font>pthread<font style="color: rgb(107, 89, 206);">],</font> <font style="color: rgb(107, 89, 206);">[</font>main<font style="color: rgb(107, 89, 206);">])</font><br><br><font style="color: rgb(0, 0, 255);"># Checks for header files.</font><br><font style="color: rgb(0, 138, 140);">AC_HEADER_STDC</font><br><font style="color: rgb(0, 138, 140);">AC_CHECK_HEADERS</font><font style="color: rgb(107, 89, 206);">([</font>arpa/inet.h libintl.h locale.h netinet/<font style="color: rgb(165, 40, 41);"><b>in</b></font>.h stdlib.h string.h sys/socket.h unistd.h<font style="color: rgb(107, 89, 206);">])</font><br><br><font style="color: rgb(0, 0, 255);"># Checks for typedefs, structures, and compiler characteristics.</font><br><font style="color: rgb(0, 138, 140);">AC_C_CONST</font><br><font style="color: rgb(0, 138, 140);">AC_TYPE_SIZE_T</font><br><br><font style="color: rgb(0, 0, 255);"># Checks for library functions.</font><br><font style="color: rgb(0, 138, 140);">AC_FUNC_FORK</font><br><font style="color: rgb(0, 138, 140);">AC_FUNC_MALLOC</font><br><font style="color: rgb(0, 138, 140);">AC_FUNC_REALLOC</font><br><font style="color: rgb(0, 138, 140);">AC_CHECK_FUNCS</font><font style="color: rgb(107, 89, 206);">([</font>inet_ntoa memset setlocale socket strcasecmp strncasecmp<font style="color: rgb(107, 89, 206);">])</font><br><br><font style="color: rgb(0, 0, 255);"># gettext</font><br><font style="color: rgb(0, 138, 140);">GETTEXT_PACKAGE</font><font style="color: rgb(165, 40, 41);"><b>=</b></font>dsrc<br><font style="color: rgb(0, 138, 140);">AC_SUBST</font><font style="color: rgb(107, 89, 206);">(</font><font style="color: rgb(0, 138, 140);">GETTEXT_PACKAGE</font><font style="color: rgb(107, 89, 206);">)</font><br><br><font style="color: rgb(0, 138, 140);">ALL_LINGUAS</font><font style="color: rgb(165, 40, 41);"><b>=</b></font><font style="color: rgb(255, 0, 255);">"zh_CN"</font><br><font style="color: rgb(0, 138, 140);">AM_GLIB_GNU_GETTEXT</font><br><br><font style="color: rgb(0, 138, 140);">AC_OUTPUT</font><font style="color: rgb(107, 89, 206);">([</font><br>Makefile<br>src/Makefile<br>po/Makefile.<font style="color: rgb(165, 40, 41);"><b>in</b></font><br><font style="color: rgb(107, 89, 206);">])</font><br></pre><br>4、准备/Makefile.am<br><pre size="12px" style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><font style="color: rgb(165, 40, 41);"><b>SUBDIRS </b></font>= src po<br><br><font style="color: rgb(0, 138, 140);">dsrcdocdir </font>= <font style="color: rgb(0, 138, 140);">${prefix}</font>/doc/dsrc<br><font style="color: rgb(165, 40, 41);"><b>dsrcdoc_DATA </b></font>= <font style="color: rgb(107, 89, 206);">\</font><br><font style="color: rgb(107, 89, 206);"> </font>README<font style="color: rgb(107, 89, 206);">\</font><br><font style="color: rgb(107, 89, 206);"> </font>COPYING<font style="color: rgb(107, 89, 206);">\</font><br><font style="color: rgb(107, 89, 206);"> </font>AUTHORS<font style="color: rgb(107, 89, 206);">\</font><br><font style="color: rgb(107, 89, 206);"> </font>ChangeLog<font style="color: rgb(107, 89, 206);">\</font><br><font style="color: rgb(107, 89, 206);"> </font>INSTALL<font style="color: rgb(107, 89, 206);">\</font><br><font style="color: rgb(107, 89, 206);"> </font>NEWS<br><br><font style="color: rgb(107, 89, 206);">EXTRA_DIST </font>= <font style="color: rgb(0, 138, 140);">$(dsrcdoc_DATA)</font><br></pre><br>其实这个内容非常简单,一看就明白了,上面所列的EXTRA_DIST为需要安装到/usr/share/doc下的东西,如果你还有其它文档可以加到这个列表中<br><br>5、准备src/Makefile.am<br><pre size="12px" style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><font style="color: rgb(0, 138, 140);">INCLUDES </font>= -DLOCALEDIR=\"<font style="color: rgb(255, 0, 255);">"</font><font style="color: rgb(0, 138, 140);">$(prefix)</font><font style="color: rgb(255, 0, 255);">/share/locale"</font>\"<br><font style="color: rgb(0, 138, 140);">AM_CFLAGS </font>= -DDEBUG -g <font style="color: rgb(0, 138, 140);">$(xml2_CFLAGS)</font><br><font style="color: rgb(0, 138, 140);">LIBS </font>= <font style="color: rgb(0, 138, 140);">$(xml2_LIBS)</font> <font style="color: rgb(0, 138, 140);">$(openssl_LIBS)</font> -lpthread<br><font style="color: rgb(0, 0, 255);"># AM_LDFLAGS =</font><br><br><font style="color: rgb(165, 40, 41);"><b>bin_PROGRAMS </b></font>= dsrc<br><font style="color: rgb(41, 138, 82);"><b>dsrc_SOURCES </b></font>= main.c security.c XML_utils.c DSRC_handler.c DSRC_builder.c<br><font style="color: rgb(0, 0, 255);"># dsrc_CFLAGS =</font><br><font style="color: rgb(0, 0, 255);"># dsrc_LDFLAGS =</font><br></pre><br>如 果会生成多个执行文件可为bin_PROGRAMS增加文件名即可,以空格隔开,下面对每个执行文件需要的源文件定义为xxx_SOURCES即可,如果 某执行文件编译参数以及链接参数也可以单独设置:xxx_CFLAGS、xxx_LDFLAGS,不过我建议库文件链接参数直接在 configure.ac里AC_CHECK_LIB了事,来得方便点<br><br>6、创建automake需要的一些文件<br><br>touch AUTHORS NEWS README INSTALL ChangeLog<br><br>7、心动从现在开始<br><br>aclocal<br>autoconf<br>intltoolize<br>autoheader<br>automake --add-missing --gnu<br><br>8、正事要紧<br><br>给自己的程序添加gettext支持,关于gettext的详细介绍可参考其它文章,一般就是以下套路<br><pre size="12px" style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><font style="color: rgb(165, 32, 247);">#include </font><font style="color: rgb(255, 0, 255);"><libintl.h></font><br><font style="color: rgb(165, 32, 247);">#include </font><font style="color: rgb(255, 0, 255);"><locale.h></font><br><br><font style="color: rgb(165, 32, 247);">#define _(string) gettext(string)</font><br><font style="color: rgb(165, 32, 247);">#define N_(string) string</font><br><br><font style="color: rgb(41, 138, 82);"><b>void</b></font><br>i18n_init(<font style="color: rgb(41, 138, 82);"><b>void</b></font>)<br>{<br> bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);<br> bind_textdomain_codeset(GETTEXT_PACKAGE, <font color="#ffa07a">"UTF-8"</font>);<br> textdomain(GETTEXT_PACKAGE);<br>}<br></pre><br>通常程序在入口处就调用i18n_init(),在显示常量字符串的时候一般如fprintf(stdout, _("Hello World\n"));<br><br>9、创建po文件<br><br>创 建并进入/po目录,创建POTFILES.in,内容为你需要提取源码中有需要翻译的字符串的源文件列表,每行一个文件,然后执行intltool- update --pot产生pot文件,如果将来你在维护代码中代码有变化或者在POTFILES.in中新增了源文件,可用intltool-update --maintain更新。<br><br>有了pot文件,现在需要产生各种语言的po文件,如msginit --locale=zh_CN产生中文po文件,如将来源文件有变化可以intltool-update zh_CN更新zh_CN.po,接下来翻译的工作就是你自己来做了。<br><br>要生成特定语言的mo文件,需要维护configure.ac中的ALL_LINGUAS,以空格分隔就可以了<br><br>10、测试<br><br>./configure --prefix=/usr<br>make<br>sudo make install<br>LANG="zh_CN.UTF-8" xxx
查看全文
发表于:2007-03-22 ┆
阅读(509)
┆
评论(0)
libxml2尝试
etc项目中实现一个http server,刚好用到大量的XML,每次处理的数据包XML数据相对较小,先尝试了expat,SAX解析方式确实痛苦,需要自己维护状态树。 libxml2相对功能比较全,SAX、DOM解析方式都有实现,而且还有XPath、XLink等实现,甚至连HTMLparser都有了,下面是我这 次用到的一些API:<br><br>1、解析XML文档DOM树(参考parser.h)<br><br>xmlDocPtr doc = xmlParseDoc((const xmlChar *)xml_data);<br>xmlNodePtr node = xmlDocGetRootElement(doc);<br>然 后node就可以在DOM树里面漫游了,当然xmlParseDoc之后理所当然应该检查doc是否为空意即解析是否成功,结束之后记得 xmlFreeDoc(doc);如果需要解析xml文件,则使用xmlParseFile(const xmlChar *)"test.xml")。<br><br>2、常见操作(参考tree.h)<br><br>得到一个节点的名称:node->name^_^<br>得到一个节点的内容:xmlChar *value = xmlNodeGetContent(node)返回值value应该使用xmlFree(value)释放内存<br>设置一个节点的内容:xmlNodeSetContent(node, (const xmlChar *)"test")<br>得到一个节点的某属性值:xmlChar *value = xmlGetProp(node, (const xmlChar *)"prop1"),返回值需要xmlFree(value)释放内存<br>设置一个节点的某属性值:xmlSetProp(node, (const xmlChar *)"prop1", (const xmlChar *)"v1")<br><br>3、新建XML文档(参考tree.h)<br><br>xmlDocPtr doc = xmlNewDoc("1.0"),其中1.0是版本号<br>doc->children = xmlNewDocNode(doc, NULL, (const xmlChar *)"stream", NULL)创建根节点,具体函数原型可参考其API-Manual<br>xmlNodePtr node = xmlNewChild(doc->children, NULL, (const xmlChar *)"dsrc_frame", NULL),用xmlNewChild可生成某节点的子节点<br>xmlDocDumpFormatMemory(doc, buf, &result, 1),用来保存生成的xml文档到内存中,此系列函数还包括:xmlDocDump、xmlDocDumpFormatMemoryEnc、 xmlDocDumpMemory、xmlDocDumpMemoryEnc、xmlDocFormatDump<br><br>4、XPath操作(参考xpath.h)(XPath可参考w3c文档http://www.w3.org/TR/xpath)<br><br>有时候对一个XML文档我们可能只关心其中某一个或某几个特定的Element的值或其属性,如果漫游DOM树将是很痛苦也很无聊的事,XPath可以非常方便地得到你想的Element。下面是一个自定义函数:<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br>xmlXPathObjectPtr<br>get_nodeset(xmlDocPtr doc, <font color="#298a52"><b>const</b></font> xmlChar *xpath)<br>{<br> xmlXPathContextPtr context;<br> xmlXPathObjectPtr result;<br><br> context = xmlXPathNewContext(doc);<br> <font color="#a52829"><b>if</b></font> (context == <font color="#ff00ff">NULL</font>)<br> <font color="#a52829"><b>return</b></font> <font color="#ff00ff">NULL</font>;<br><br> result = xmlXPathEvalExpression(xpath, context);<br> xmlXPathFreeContext(context);<br> <font color="#a52829"><b>if</b></font> (result == <font color="#ff00ff">NULL</font>)<br> <font color="#a52829"><b>return</b></font> <font color="#ff00ff">NULL</font>;<br> <font color="#a52829"><b>if</b></font> (xmlXPathNodeSetIsEmpty(result->nodesetval)) {<br> xmlXPathFreeObject(result);<br> <font color="#a52829"><b>return</b></font> <font color="#ff00ff">NULL</font>;<br> }<br><br> <font color="#a52829"><b>return</b></font> result;<br>}<br></pre><br>下面是调用代码:<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br>xmlXPathObjectPtr app_result = get_nodeset(doc, (<font color="#298a52"><b>const</b></font> xmlChar *)<font color="#ff00ff">"/stream/dsrc_frame/tapdu/application[1]/param"</font>);<br><font color="#a52829"><b>if</b></font> (app_result == <font color="#ff00ff">NULL</font>)<br> <font color="#a52829"><b>return</b></font> <font color="#ff00ff">0</font>;<br><br>xmlNodeSetPtr nodeset = app_result->nodesetval;<br>xmlChar *value = xmlNodeGetContent(nodeset->nodeTab[<font color="#ff00ff">0</font>]);<br><font color="#a52829"><b>if</b></font> (value == <font color="#ff00ff">NULL</font>)<br> <font color="#a52829"><b>goto</b></font> ret;<br><br>printf(<font color="#ff00ff">"</font><font color="#6b59ce">%s</font><font color="#6b59ce">\n</font><font color="#ff00ff">"</font>, value);<br><br>xmlXPathFreeObject(app_result);<br>xmlFree(value);</pre>
查看全文
发表于:2007-03-22 ┆
阅读(977)
┆
评论(0)
善用backtrace解决大问题
程序在得到一个Segmentation fault这样的错误信息毫无保留地就跳出来了,遇到这样的问题让人很痛苦,查找问题不亚于你N多天辛苦劳累编写代码的难度。那么有没有更好的方法可以在产生SIGSEGV信号的时候得到调试可用的信息呢?看看下面的例程吧!<br><br>sigsegv.h<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#fa8072">#if</font><font color="#fa8072">n</font><font color="#fa8072">def</font> __sigsegv_h__<br><font color="#fa8072">#define</font> <font color="#7fffd4"><b>__sigsegv_h__</b></font><br><br><font color="#fa8072">#ifdef</font> __cplusplus<br><font color="#fa8072">extern</font> <font color="#ffa07a">"C"</font> {<br><font color="#fa8072">#endif</font><br><br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>setup_sigsegv</b></font>();<br><br><font color="#fa8072">#ifdef</font> __cplusplus<br>}<br><font color="#fa8072">#endif</font><br><br><font color="#fa8072">#endif</font> /* <font color="#add8e6">__sigsegv_h__ </font>*/<br></pre><br>sigsegv.c<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#fa8072">#define</font> <font color="#7fffd4"><b>_GNU_SOURCE</b></font><br><font color="#fa8072">#include</font> <<font color="#ffa07a">memory.h></font><br><font color="#fa8072">#include</font> <<font color="#ffa07a">stdlib.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><stdio.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><signal.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><ucontext.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><dlfcn.h></font><br><font color="#fa8072">#include</font> <font color="#ffa07a"><execinfo.h></font><br><font color="#fa8072">#if</font><font color="#fa8072">n</font><font color="#fa8072">def</font> NO_CPP_DEMANGLE<br><font color="#fa8072">#include</font> <font color="#ffa07a"><cxxabi.h></font><br><font color="#fa8072">#endif</font><br><br><font color="#fa8072">#if</font> <font color="#fa8072">defined</font>(REG_RIP)<br><font color="#fa8072"># define</font> <font color="#7fffd4"><b>SIGSEGV_STACK_IA64</b></font><br><font color="#fa8072"># define</font> <font color="#7fffd4"><b>REGFORMAT</b></font> <font color="#ffa07a">"%016lx"</font><br><font color="#fa8072">#elif</font> <font color="#fa8072">defined</font>(REG_EIP)<br><font color="#fa8072"># define</font> <font color="#7fffd4"><b>SIGSEGV_STACK_X86</b></font><br><font color="#fa8072"># define</font> <font color="#7fffd4"><b>REGFORMAT</b></font> <font color="#ffa07a">"%08x"</font><br><font color="#fa8072">#else</font><br><font color="#fa8072"># define</font> <font color="#7fffd4"><b>SIGSEGV_STACK_GENERIC</b></font><br><font color="#fa8072"># define</font> <font color="#7fffd4"><b>REGFORMAT</b></font> <font color="#ffa07a">"%x"</font><br><font color="#fa8072">#endif</font><br><br><font color="#fa8072">static</font> <font color="#9acd32"><b>void</b></font> <font color="#7fffd4"><b>signal_segv</b></font>(<font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>signum</b></font>, <font color="#9acd32"><b>siginfo_t</b></font>* <font color="#7fffd4"><b>info</b></font>, <font color="#9acd32"><b>void</b></font>*<font color="#7fffd4"><b>ptr</b></font>) {<br> <font color="#fa8072">static</font> <font color="#fa8072">const</font> <font color="#9acd32"><b>char</b></font> *<font color="#7fffd4"><b>si_codes</b></font>[3] = {<font color="#ffa07a">""</font>, <font color="#ffa07a">"SEGV_MAPERR"</font>, <font color="#ffa07a">"SEGV_ACCERR"</font>};<br><br> <font color="#9acd32"><b>size_t</b></font> <font color="#7fffd4"><b>i</b></font>;<br> <font color="#9acd32"><b>ucontext_t</b></font> *<font color="#7fffd4"><b>ucontext</b></font> = (<font color="#9acd32"><b>ucontext_t</b></font>*)ptr;<br><br><font color="#fa8072">#if</font> <font color="#fa8072">defined</font>(SIGSEGV_STACK_X86) || <font color="#fa8072">defined</font>(SIGSEGV_STACK_IA64)<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>f</b></font> = 0;<br> <font color="#9acd32"><b>Dl_info</b></font> <font color="#7fffd4"><b>dlinfo</b></font>;<br> <font color="#9acd32"><b>void</b></font> **<font color="#7fffd4"><b>bp</b></font> = 0;<br> <font color="#9acd32"><b>void</b></font> *<font color="#7fffd4"><b>ip</b></font> = 0;<br><font color="#fa8072">#else</font><br> <font color="#9acd32"><b>void</b></font> *<font color="#7fffd4"><b>bt</b></font>[20];<br> <font color="#9acd32"><b>char</b></font> **<font color="#7fffd4"><b>strings</b></font>;<br> <font color="#9acd32"><b>size_t</b></font> <font color="#7fffd4"><b>sz</b></font>;<br><font color="#fa8072">#endif</font><br><br> fprintf(stderr, <font color="#ffa07a">"Segmentation Fault!\n"</font>);<br> fprintf(stderr, <font color="#ffa07a">"info.si_signo = %d\n"</font>, signum);<br> fprintf(stderr, <font color="#ffa07a">"info.si_errno = %d\n"</font>, info->si_errno);<br> fprintf(stderr, <font color="#ffa07a">"info.si_code = %d (%s)\n"</font>, info->si_code, si_codes[info->si_code]);<br> fprintf(stderr, <font color="#ffa07a">"info.si_addr = %p\n"</font>, info->si_addr);<br> <font color="#fa8072">for</font>(i = 0; i &lt; NGREG; i++)<br> fprintf(stderr, <font color="#ffa07a">"reg[%02d] = 0x"</font> REGFORMAT <font color="#ffa07a">"\n"</font>, i, ucontext->uc_mcontext.gregs[i]);<br><br><font color="#fa8072">#if</font> <font color="#fa8072">defined</font>(SIGSEGV_STACK_X86) || <font color="#fa8072">defined</font>(SIGSEGV_STACK_IA64)<br><font color="#fa8072"># if</font> <font color="#fa8072">defined</font>(SIGSEGV_STACK_IA64)<br> ip = (<font color="#9acd32"><b>void</b></font>*)ucontext->uc_mcontext.gregs[REG_RIP];<br> bp = (<font color="#9acd32"><b>void</b></font>**)ucontext->uc_mcontext.gregs[REG_RBP];<br><font color="#fa8072"># elif</font> <font color="#fa8072">defined</font>(SIGSEGV_STACK_X86)<br> ip = (<font color="#9acd32"><b>void</b></font>*)ucontext->uc_mcontext.gregs[REG_EIP];<br> bp = (<font color="#9acd32"><b>void</b></font>**)ucontext->uc_mcontext.gregs[REG_EBP];<br><font color="#fa8072"># endif</font><br><br> fprintf(stderr, <font color="#ffa07a">"Stack trace:\n"</font>);<br> <font color="#fa8072">while</font>(bp && ip) {<br> <font color="#fa8072">if</font>(!dladdr(ip, &dlinfo))<br> <font color="#fa8072">break</font>;<br><br> <font color="#fa8072">const</font> <font color="#9acd32"><b>char</b></font> *<font color="#7fffd4"><b>symname</b></font> = dlinfo.dli_sname;<br><font color="#fa8072">#if</font><font color="#fa8072">n</font><font color="#fa8072">def</font> NO_CPP_DEMANGLE<br> <font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>status</b></font>;<br> <font color="#9acd32"><b>char</b></font> *<font color="#7fffd4"><b>tmp</b></font> = __cxa_demangle(symname, <font color="#7fffd4">NULL</font>, 0, &status);<br><br> <font color="#fa8072">if</font>(status == 0 && tmp)<br> symname = tmp;<br><font color="#fa8072">#endif</font><br><br> fprintf(stderr, <font color="#ffa07a">"% 2d: %p <%s+%u> (%s)\n"</font>,<br> ++f,<br> ip,<br> symname,<br> (<font color="#9acd32"><b>unsigned</b></font>)(ip - dlinfo.dli_saddr),<br> dlinfo.dli_fname);<br><br><font color="#fa8072">#if</font><font color="#fa8072">n</font><font color="#fa8072">def</font> NO_CPP_DEMANGLE<br> <font color="#fa8072">if</font>(tmp)<br> free(tmp);<br><font color="#fa8072">#endif</font><br><br> <font color="#fa8072">if</font>(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, <font color="#ffa07a">"main"</font>))<br> <font color="#fa8072">break</font>;<br><br> ip = bp[1];<br> bp = (<font color="#9acd32"><b>void</b></font>**)bp[0];<br> }<br><font color="#fa8072">#else</font><br> fprintf(stderr, <font color="#ffa07a">"Stack trace (non-dedicated):\n"</font>);<br> sz = backtrace(bt, 20);<br> strings = backtrace_symbols(bt, sz);<br><br> <font color="#fa8072">for</font>(i = 0; i < sz; ++i)<br> fprintf(stderr, <font color="#ffa07a">"%s\n"</font>, strings[i]);<br><font color="#fa8072">#endif</font><br> fprintf(stderr, <font color="#ffa07a">"End of stack trace\n"</font>);<br> exit (-1);<br>}<br><br><font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>setup_sigsegv</b></font>() {<br> <font color="#fa8072">struct</font> <font color="#9acd32"><b>sigaction</b></font> <font color="#7fffd4"><b>action</b></font>;<br> memset(&action, 0, <font color="#fa8072">sizeof</font>(action));<br> action.sa_sigaction = signal_segv;<br> action.sa_flags = SA_SIGINFO;<br> <font color="#fa8072">if</font>(sigaction(SIGSEGV, &action, <font color="#7fffd4">NULL</font>) < 0) {<br> perror(<font color="#ffa07a">"sigaction"</font>);<br> <font color="#fa8072">return</font> 0;<br> }<br><br> <font color="#fa8072">return</font> 1;<br>}<br><br><font color="#fa8072">#if</font><font color="#fa8072">n</font><font color="#fa8072">def</font> SIGSEGV_NO_AUTO_INIT<br><font color="#fa8072">static</font> <font color="#9acd32"><b>void</b></font> <font color="#7fffd4"><b>__attribute</b></font>((constructor)) <font color="#7fffd4"><b>init</b></font>(<font color="#9acd32"><b>void</b></font>) {<br> setup_sigsegv();<br>}<br><font color="#fa8072">#endif</font><br></pre><br>main.c<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#fa8072">#include</font> <font color="#ffa07a">"sigsegv.h"</font><br><font color="#fa8072">#include</font> <<font color="#ffa07a">string.h></font><br><br><font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>die</b></font>() {<br> <font color="#9acd32"><b>char</b></font> *<font color="#7fffd4"><b>err</b></font> = <font color="#7fffd4">NULL</font>;<br> strcpy(err, <font color="#ffa07a">"gonner"</font>);<br> <font color="#fa8072">return</font> 0;<br>}<br><br><font color="#9acd32"><b>int</b></font> <font color="#7fffd4"><b>main</b></font>() {<br> <font color="#fa8072">return</font> die();<br>}<br></pre><br>下面来编译上面的main.c程序看看将会产生什么样的信息呢,不过要注意的就是如果要在你的程序里引用sigsegv.h、sigsegv.c得到堆栈信息的话记得加上-rdynamic -ldl参数。<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#ffc0cb"><b>/data/codes/c/test/backtraces $ </b></font>gcc -o test -rdynamic -ldl -ggdb -g sigsegv.c main.c<br><font color="#ffc0cb"><b>/data/codes/c/test/backtraces $ </b></font>./test<br>Segmentation Fault!<br>info.si_signo = 11<br>info.si_errno = 0<br>info.si_code = 1 (SEGV_MAPERR)<br>info.si_addr = (nil)<br>reg[00] = 0x00000033<br>reg[01] = 0x00000000<br>reg[02] = 0xc010007b<br>reg[03] = 0x0000007b<br>reg[04] = 0x00000000<br>reg[05] = 0xb7fc8ca0<br>reg[06] = 0xbff04c2c<br>reg[07] = 0xbff04c1c<br>reg[08] = 0xb7f8cff4<br>reg[09] = 0x00000001<br>reg[10] = 0xbff04c50<br>reg[11] = 0x00000000<br>reg[12] = 0x0000000e<br>reg[13] = 0x00000006<br>reg[14] = 0x080489ec<br>reg[15] = 0x00000073<br>reg[16] = 0x00010282<br>reg[17] = 0xbff04c1c<br>reg[18] = 0x0000007b<br>Stack trace:<br> 1: 0x80489ec <die+16> (/data/codes/c/test/backtraces/test)<br> 2: 0x8048a16 <main+19> (/data/codes/c/test/backtraces/test)<br>End of stack trace<br><font color="#ffc0cb"><b>/data/codes/c/test/backtraces $ </b></font></pre><br>下面用gdb来看看出错的地方左右的代码:<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#ffc0cb"><b>/data/codes/c/test/backtraces $ </b></font>gdb ./test<br>gdb> disassemble die+16<br>Dump of assembler code for function die:<br>0x080489dc <die+0>: push %ebp<br>0x080489dd <die+1>: mov %esp,%ebp<br>0x080489df <die+3>: sub $0x10,%esp<br>0x080489e2 <die+6>: movl $0x0,0xfffffffc(%ebp)<br>0x080489e9 <die+13>: mov 0xfffffffc(%ebp),%eax<br>0x080489ec <die+16>: movl $0x6e6e6f67,(%eax)<br>0x080489f2 <die+22>: movw $0x7265,0x4(%eax)<br>0x080489f8 <die+28>: movb $0x0,0x6(%eax)<br>0x080489fc <die+32>: mov $0x0,%eax<br>0x08048a01 <die+37>: leave <br>0x08048a02 <die+38>: ret <br>End of assembler dump.<br>gdb&gt; </pre><br>也可以直接break *die+16进行调试,看看在出错之前的堆栈情况,那么下面我们再来看看代码问题到底出在什么地方了。<br><pre style="font-size: 12px; color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><br><font color="#ffc0cb"><b>/data/codes/c/test/backtraces $ </b></font>gdb ./test<br>gdb> break *die+16<br>Breakpoint 1 at 0x80489f2: file main.c, line 6.<br>gdb&gt; list *die+16<br>0x80489f2 is in die (main.c:6).<br>1 #include "sigsegv.h"<br>2 #include <string.h><br>3 <br>4 int die() {<br>5 char *err = NULL;<br>6 strcpy(err, "gonner");<br>7 return 0;<br>8 }<br>9 <br>10 int main() {<br>gdb> </pre><br>现 在看看定位错误将会多么方便,上面的调试指令中list之前break不是必须的,只是让你可以看到break其实就已经指出了哪一行代码导致 Segmentation fault了。如果你要发布你的程序你一般会为了减少体积不会附带调试信息的(也就是不加-ggdb -g参数),不过没关系,你一样可以得到上面stack-trace信息,然后你调试之前只要加上调试信息即可。
查看全文
发表于:2007-03-22 ┆
阅读(1180)
┆
评论(0)
又见Makefile
自从用了autotools很久不曾有过编写Makefile的经历了,这两天维护客户以前让别的公司给做的一个项目中的代码,写了个Makefile感觉挺不错。。。<pre style="color: rgb(245, 222, 179); background-color: rgb(47, 79, 79);"><font color="#7fffd4"><b>CC</b></font> = g++<font color="#7fffd4"><b><br>GTK_CFLAGS</b></font> = $(<font color="#7fffd4"><b>shell</b></font><font color="#7fffd4"><b> </b></font>gdk-pixbuf-config --cflags)<br><font color="#7fffd4"><b>GTK_LIBS</b></font> = $(<font color="#7fffd4"><b>shell</b></font><font color="#7fffd4"><b> </b></font>gdk-pixbuf-config --libs) $(<font color="#7fffd4"><b>shell</b></font><font color="#7fffd4"><b> </b></font>pkg-config --libs gthread)<br><font color="#7fffd4"><b>MYSQL_CFLAGS</b></font> = $(<font color="#7fffd4"><b>shell</b></font><font color="#7fffd4"><b> </b></font>mysql_config --cflags)<br><font color="#7fffd4"><b>MYSQL_LIBS</b></font> = $(<font color="#7fffd4"><b>shell</b></font><font color="#7fffd4"><b> </b></font>mysql_config --libmysqld-libs)<br><font color="#7fffd4"><b>CFLAGS</b></font> = $(<font color="#7fffd4"><b>GTK_CFLAGS</b></font>) $(<font color="#7fffd4"><b>MYSQL_CFLAGS</b></font>) -I/usr/include/lclibs -DMYSQL_EMBED -DETC_THREAD<br><font color="#7fffd4"><b>LIBS</b></font> = $(<font color="#7fffd4"><b>GTK_LIBS</b></font>) $(<font color="#7fffd4"><b>MYSQL_LIBS</b></font>) -L./libs -ldl -rdynamic -llclibs -ldsrc -lgts<br><br><font color="#7fffd4"><b>SRC_PATH</b></font> = src<br><font color="#7fffd4"><b>OBJ_PATH</b></font> = obj<font color="#7fffd4"><b><br>SOURCES</b></font> = $(<font color="#7fffd4"><b>wildcard</b></font><font color="#7fffd4"><b> </b></font>$(<font color="#7fffd4"><b>SRC_PATH</b></font>)/*.c)<font color="#7fffd4"><b><br>OBJECTS</b></font> = $(<font color="#7fffd4"><b>patsubst</b></font><font color="#7fffd4"><b> </b></font>$(<font color="#7fffd4"><b>SRC_PATH</b></font>)/%.c, $(<font color="#7fffd4"><b>OBJ_PATH</b></font>)/%.o, $(<font color="#7fffd4"><b>SOURCES</b></font>))<br><font color="#7fffd4"><b>DEPENDS</b></font> = $(<font color="#7fffd4"><b>patsubst</b></font><font color="#7fffd4"><b> </b></font>$(<font color="#7fffd4"><b>SRC_PATH</b></font>)/%.c, $(<font color="#7fffd4"><b>OBJ_PATH</b></font>)/%.d, $(<font color="#7fffd4"><b>SOURCES</b></font>))<br><br>all: hwetc<br><br>$(<font color="#7fffd4"><b>DEPENDS</b></font>): $(<font color="#7fffd4"><b>OBJ_PATH</b></font>)/%.d: $(<font color="#7fffd4"><b>SRC_PATH</b></font>)/%.c<br> $(<font color="#7fffd4"><b>CC</b></font>) -MM $(<font color="#7fffd4"><b>CFLAGS</b></font>) $<font color="#7fffd4"><</font> > $<font color="#7fffd4">@</font>; \<br> sed -i <font color="#ffa07a">'s,\(</font><font color="#ffa07a">$</font><font color="#7fffd4">*</font><font color="#ffa07a">\)\.o[ :]*,$(</font><font color="#7fffd4"><b>OBJ_PATH</b></font><font color="#ffa07a">)/\1.o </font><font color="#ffa07a">$</font><font color="#7fffd4">@</font><font color="#ffa07a"> : ,g'</font> $<font color="#7fffd4">@</font><font color="#fa8072">include</font> $(<font color="#7fffd4"><b>DEPENDS</b></font>)<br><br>hwetc: $(<font color="#7fffd4"><b>OBJECTS</b></font>)<br> $(<font color="#7fffd4"><b>CC</b></font>) $(<font color="#7fffd4"><b>OBJECTS</b></font>) $(<font color="#7fffd4"><b>LIBS</b></font>) -o $<font color="#7fffd4">@<br><br></font>$(<font color="#7fffd4"><b>OBJECTS</b></font>):<br> $(<font color="#7fffd4"><b>CC</b></font>) -c $(<font color="#7fffd4"><b>CFLAGS</b></font>) $<font color="#7fffd4"><</font> -o $<font color="#7fffd4">@<br><br></font>.PHONY: clean<br>clean: rm -f hwetc $(<font color="#7fffd4"><b>OBJECTS</b></font>) $(<font color="#7fffd4"><b>DEPENDS</b></font>)</pre>ps: 之所以CC = g++是因为其中用到gts等C++写就的library,而且头文件里就包含有C++语法,因此将就着应付一下。。。
查看全文
发表于:2007-03-22 ┆
阅读(348)
┆
评论(0)