??xml version="1.0" encoding="utf-8" standalone="yes"?>
1.configure文g?455?467行注释掉.
2.修改libutil/path.c文g. 在include之后d:
#if defined(_WIN32) && !defined(__CYGWIN__)
#define
mkdir(path,mode) mkdir(path)
#define link(one,two) (-1)
#endif
上述两个文g保存? configure, make, make install卛_.
用这U方式除了doc下的texi文g没法~译成功, 其他都没有问? ~译到doc的时? 直接C-cl束卛_.
q篇文章基本上是摘自gdb手册Q除此之外就是加了实际的代码样例Q这样可以更清楚的看C些命令的执行效果。当Ӟq儿不会涉及到所有的gdb命oQ而只是一些常用的?/p>
我这儿用的gdb的版本是6.8。不q因为只是一些常用命令,因此在老版本上应该也没问题。操作系l是Windows XP?/p>
调试器的目的在于让你查看E序q行时的内部状态;或者在E序崩溃的时候,查看E序异常的原因。它们可以在一下几个方面提供帮助:
1)启动E序Q按照你的意愿媄响程序的行ؓ
2)让程序在特定条g发生时停止运?/p>
3)当程序停止的时候,查程序正在做什?/p>
4)改变E序的某些东西,q样可以运行时修正bugQ然后l测试其他的问题?/p>
gdb支持多种语言的调试,不过最成熟的应该就是c/c++了。这儿也以c++E序Z来说明。如果想知道其他语言的支持情况,可以看gdb手册?/p>
gdb最常用的启动方式就是:
gdb program
或者在E序异常l止的时候这P
gdb program core
也或者,你可以attachC个已l运行的q程来调试它Q就像这?
gdb program PID
当然Q也可以在命令行讄gdb的启动参敎ͼ例如argsQ?
gdb —args gcc -O2 -c foo.c
q样可以调试gccQ同时将参数"-O2 -c foo.c"传给gcc?/p>
可以用gdb -help查看gdb的所有选项?/p>
要想中止gdb的运行,可以输入quit或者qQ也可以按ctrl-dl合键?/p>
gdb命o的Ş式ؓQcommand [arg1...argn]。每个命令单独一行。行的长度没有限Ӟ当然Q一般应该也不会有多长)?/p>
许多gdb的命令都会有~写的Ş式,例如break可以~写为b?/p>
如果直接按回车,gdb会执行刚刚被执行命o?/p>
如果命o中有#字符Q那么从#开始的字符都会被当成是注释。这个一般用在命令文件中。后面会有介l?/p>
gdbh补全功能。功能键?lt;TAB>。例如breakQ在输入bre之后?lt;TAB> 键,gdb׃补全为break。如果只输入bQ然后按<TAB>Qgdb会响一壎ͼq说明有多个以b开始的命o。这U情况下再按一 ?lt;TAB>Qgdb׃把所有以b开始的命o输出出来。下面是此时的屏q截图:
如果只是想看一下以某个(?字符开始的命oQ可以按<META>?Q而不用按两次<TAB>。在? ?lt;META>键的电脑上,可以?lt;ESC>键代ѝ这个命令按h有点ȝQ比按两?lt;TAB>要麻烦多了,如果 不?lt;TAB>键被按坏Q我你还是按<TAB>吧?/p>
命o补全可以用于gdb命oQgdb子命令,E序中的W号名(例如函数名等Q?/p>
在调试c++E序Ӟ基本上肯定会遇到的问题就是重载函数。例如,在设|断点的时候,假设有两个名为overload的函敎ͼq时Z区分到底是那 个函敎ͼ需要加上函数参数类型(函数名加上参数列表作为逻辑上的一个词Q。ؓ了gdb能将参数列表两边的括号作个词的一部分Q需要用单引?函 数整个的括v来。看下图Q?/p>
启动gdb后,可以输入命ohelp得到gdb的命令列表。注意的是这时输出的每个条目都是一cd令。上个图Q?
得到命ocd后,可以用命?help class得到此类别的所有命令。上图:
上面的图中只昄了部分breakpoints命o?/p>
其他跟帮助相关的命o有:
a)help command
用于昄命ocommand的帮助信息?/p>
b)apropos args
q里的args可以使正则表辑ּ。显C所有匹配args的命令的要说明?/p>
c)complete args
昄所有以args开始的命o?/p>
另外q有两个很有用的命oQ?info ?show ?/p>
a)info
用于昄被调试程序的信息。例如传递到当前函数的参?info args;或者查看当前寄存器的?info registers;也可以查看断?info breakpoints。可以用help info查看info的说明?/p>
b)show
q个命o用于昄gdb的信息。也是gdb的一些属性倹{可以用help show查看帮助信息。这个命令通常应该是配合set用的Q用于设定gdb的属性)?/p>
好了Q现在对gdb应该有个大概的认识了Q下面我们就要拿几个例子来验证一些常用命令的效果。Let's go!
首先说明一点,要想高效的用gdb的功能,需要在~译E序的时候要加上-g选项Q这个选项会把调试信息加到可执行文件中?/p>
下面说一下示例文Ӟ包括三个Qgdb.hQ?gdb.cppQ?test.cpp
gdb.h#ifndef _GDB_Hgdb.cpp
#define _GDB_H 1
class gdb
{
public:
explicit gdb(int v);
void overload(int one);
void overload(int one, int two);
void catch_ex(int ex); //exception
void loop();
private:
int value;
int array[10];
};
#endif
#include "gdb.h"test.cpp
#include <iostream>
using namespace std;
gdb::gdb(int v)
{
value = v;
for(int i=0; i<10; i++)
{
array[i] = i;
}
}
void gdb::overload(int one)
{
cout<<"function overload with one parameter: "<<one<<endl;
}
void gdb::overload(int one, int two)
{
cout<<"function overload with two paremeters: "<<one<<" "<<two<<endl;
}
void gdb::loop()
{
int loop_array[10];
for(int i=0; i<10; i++)
{
loop_array[i] = i;
}
int v=3;
v=3;
v=4;
}
void gdb::catch_ex(int ex)
{
int e = ex;
try
{
if(e <= 0)
{
throw e;
}
else
{
cout<<"function catch_ex: "<<ex<<endl;
}
}
catch(int x)
{
cout<<"exception: "<<x<<endl;
}
}
#include "gdb.h"
int main()
{
gdb g(5);
g.overload(1);
g.overload(1, 2);
g.loop();
g.catch_ex(3);
g.catch_ex(-1);
return 0;
}
好了Q现在开始调试。首先启动gdbQ指定要调试的可执行文g。前面已l说q了Q可以简单地使用gdb program来启动。或者可以首先启动gdbQ然后用file命o指定要调试的文g。下面是仅启动gdb后的画面Q?
现在用file命o指定要调试的文gQ?/p>
然后可以用 run 或?r 命o来运行程序。在q行之前Q你可能需要ؓE序讑֮一些信息,q些信息有一下四U:
1)E序参数
可以用set args命o讑֮E序的参数。设定完后可以用show args查看讄的是否正。如果set args后面不带M参数Q则向程序传递的参数为空?/p>
2)环境
q儿的环境就是在pȝ/用户配置文g中设|的环境变量,像HOME, PATH之类?GDB提供了在调试的时候改变这些变量值的方式,q样当需要的时候就不用退出gdb来重新设|?GDB提供的命令有:
a) path directory Q- ?directory 加到环境变量PATH前面. 注意 对PATH的改变只对调试的E序有效, GDB使用的PATH不会有改?1
b) show paths Q- 昄PATH的倹{?/p>
c) show environment [varname] Q- 昄环境变量varname的|如果不指定varnameQ则昄所有环境变量的倹{?/p>
d) set environment varname [= value] Q- 讄环境变量varname的gؓvalue。这个改变只是对调试的程序生效。如果不提供valueQ则varname的值置为空?/p>
e) unset environment varname Q- 从环境中U除传递给E序的变量varname?/p>
3)工作目录
在启动gdb调试E序的时候,被调试的E序会从gdbl承工作目录。当然gdb也提供了命o来修改工作目录:
a) cd directory Q- ?directory 设ؓ新的工作目录?/p>
b) pwd Q- 昄当前工作目录?/p>
4)标准输入输出
q没扑ֈ在windows里面q个东西有啥用,现在也没有linux可用Q不好多说。有需要的自己看gdb手册吧。我单抄一下手册吧?/p>
在gdb中,可以run命o的输入输出重定向到文件或者其他终端。也可以通过tty命o讄被调试程序输入输出的讑֤。命令格式是Q?/p>
tty terminal 或?set inferior-tty terminal.
tty 是 set inferior-tty 的别名?/p>
咚咚咚咚Q下面正式开始!
上面我们已经启动了程? 也知道了如何q行E序。可是如果你直接执行run命o会发玎ͼE序直接q行l束了。如果你惛_某一行或者某个函数调用的地方Q或者当某个变量/表达式的值改变的时候,也或者在某些事g发生的时候-Q例如抛出异常、加载动态库Q或者创建子q程Q-的时候停止程序运行,那应该怎么办呢Q?/p>
有了gdbQ一切就都好办了:), 利用下面q三个强大的武器Q你可以L的停止程序。小心了Q大家小心了Q偶要祭三g宝物了,它们是:
断点是指定一个位|,使得E序q行到这个位|的时候会停下来(当然Q还可以讄条g断点Q当q行到指定位|时Q只有满了讄的条ӞE序才会停下来)Q这样便于观察程序的内部状态。断点相关的命o主要有:
a)break location
在指定位|?location 处设|断点,q里?location 可以是函数名Q行P指o地址{(关于如何指定 location ,可以?a href="http://www.shnenglu.com/lucency/archive/2008/08/18/59214.html#location">q里Q?/p>
b)break
如果不指定Q何参敎ͼbreak会在选定?a href="http://www.shnenglu.com/lucency/archive/2008/08/18/59214.html#stack">栈的下一条指令处讄断点?/p>
c)break ... if cond
讄条g断点。每ơ到达断点的时候都会对表达?cond 求|只有当结果ؓ?的时候程序才会在q个断点停下来?/p>
d)tbreak args
讄一个只生效一ơ的断点。args跟break命o里的参数意义相同Q也是_可以为locationQؓI,或者条Ӟ?/p>
e)hbreak args
讄g断点?/p>
f)thbreak args
讄只生效一ơ的g断点?/p>
g)rbreak regex
在所有匹配正则表辑ּ regex 的函C讄断点?/p>
h)info breakpoints [n]
i)info break [n]
j)info watchpoints [n]
上面三个命o都是列出当前的断炏V观察点和捕捉点Q如果指定参数nQ则仅列出第n个的信息?/p>
来试验一把吧。首先用gdb启动E序Q假设我们想在test.cpp?g.overload(1) q一行添加一个断点,那就执行命oQb test.cpp:6,执行完后Q?/p>
q时可以用info break{命令查看断点信息:
然后我们q行E序Q看看有什么效果?/p>
看到了吧Q程序停在了断点所在的行。这时可以用where或者frame查看当前的栈帧信息,也可以用 print 查看一些变量或者表辑ּ的信息,或者info args查看参数信息Q等{?/p>
其他的命令大家可以自己尝试一下?/p>
有时候我们ƈ不确定要在哪里加断点Q例如当我们惛_某个变量被改变或者被诅R被写的时候让E序停下来,可能׃讉K变量的地Ҏ较多Q要x个地斚w加上断点比较ȝQ而且很可能有遗漏Q这时候我们就需要依赖另一个强大的命o了,也就是观察点?/p>
观察Ҏ一cȝD的断点Q如果针Ҏ个变量或者表辑ּ指定一个观察点Q那么当它们的D?写的时候,gdb会停止程序的执行。你不需要像讄断点旉h指定这个观察点在程序中的位|。观察点相关的命令有Q?/p>
a)watch expr [thread threadnum]
?expr 讄一个观察点。当 expr 的D改变的时候,gdb会停止程序的q行?/p>
如果指定了线E参数thread threadnum Q则 只有 在线E?threadnum 改变 expr 的值时Q程序才会停止?/p>
b)rwatch expr [thread threadnum]
?expr 讄一个读观察炏V当E序?expr 的值时Qgdb会停止程序的q行?/p>
c)awatch expr [thread threadnum]
?expr 讄一个访问观察点。当E序L者写 expr Ӟgdb会停止程序的q行?/p>
d)info watchpoints
昄所有的断点、观察点、捕捉点。跟info break 相同?/p>
下面再来看看观察点的使用?/p>
首先我们讄一个断点在g.loop()q一行,然后q行到这里。stepq入loop()函数。这一串命令的执行如下Q?/p>
q时我们已经q入loop()函数Q现在我们设|几个观察点。设|命令序列和讄完后的效果如:
可以看到?个停止点Q其中前两个是我们设|的断点Q后面三个是观察炏V分别ؓwatch, rwatch ?awatch。另外还有一个地方就是,x86上默认是g观察炏V?/p>
好了Q来q行一下试试?/p>
到达W一个观察点的时候程序停止运行,同时打印Z变量的旧值和新|以及观察点的位置?/p>
下面我们接着q行Q看看遇到后面的观察点的时候又会怎样?/p>
E序在第三个观察点停了下来(W二个观察点观察点)Q同h印出了变量的新旧值和观察点的位置。第二个观察点由于是读观察点Q而程序中没有读这个变量的地方Q因此运行的时候被跌了。ؓ了看一下读观察点的效果Q我们再讄一个读观察点:
i是@环内的P代器Q它会被复制lloop_array[i]变量Q也是会被诅R可以看刎ͼE序会停止运行,输出i的倹{注意:每次对i的读操作都会使得E序停止。下面是两次执行continue命o后的输出Q?/p>
观察点的内容差不多就q些了。另外有个需要注意的地方是: watch命o讄的观察点只有在变量或者表辑ּ的D改变得时候才会得程序停止运行,如果只是被写Q但是值没有改变,则程序不会停止?/strong>
上面已经讲了断点、观察点Q而对于某些情况,q两U停止点q不是最有效的方式。例如想在c++E序中跑出异常的时候停 止程序,q时候用断点׃够有效了Q因为程序中可能好多异常处理的地方,如果一个个讄断点Q那太ȝ了(当然如果只处理某几个异常Q用断点也无不可Q? 甚至用v来更灉|Q;而观察点更不可用了?/p>
q种情况需要用到捕捉点了?/p>
捕捉点也是一cȝD的断点Q它可以使得E序在某U事件发生时停止q行Q例如c++异常Q或者加载动态库、创建子q程{。设|捕捉点的命令是catch.
catch event
其中 event 可以是:
a)throw
c++抛出异常?/p>
b)catch
c++捕捉异常?/p>
c)exception
Ada异常?/p>
d)exception unhandled
E序中未处理的异常?/p>
e)assert
p|的Ada断言?/p>
f)exec
对exec的调用(只在HP-UX和GNU/Linux中可用)?/p>
g)fork
对fork的调用(只在HP-UX和GNU/Linux中可用)?/p>
h)vfork
对vfork的调用(只在HP-UX和GNU/Linux中可用)?/p>
i)load
动态加载共享库Q只在HP-UX中可用)?/p>
j)load libname
动态加载共享库 libname Q只在HP-UX中可用)?/p>
k)unload
卸蝲已加载的׃n库(只在HP-UX中可用)?/p>
l)unload libname
卸蝲已加载的׃n?libname Q只在HP-UX中可用)?/p>
q有一个设|只生效一ơ的捕捉点的命o是: tcatch event ?/p>
下面再看一下捕捉点的用?/p>
首先在vtest.cpp?g.catch_ex(-1); 讄一个断点,然后q行Q进入此函数?/p>
现在我们讄一个捕捉点。l运行:
可以看到E序在抛出异常的地方停止了?/p>
当断点不再需要了Q那应该删除掉Q否则每ơ执行到断点的位|程序都要停下来Q会把h逼疯的。删除断点的命o有两个:clear和delete?/p>
a)clear [ location ]
如果不指?location Q则删除选择的栈帧中下一条要执行的指令上的Q何断炏V如果选择的是最内部的栈帧(也就是当前正执行的函数的栈Q,则clear会将刚刚使程序停止的断点被删除? 关于 location 的说明可以看q里?/p>
b)delete [breakpoints] [ range ... ]
删除指定范围 range 那的所有的断点、观察点、捕捉点。如果不指定参数 range Q则会删除所有的停止炏V这里的 range 指定的是断点~号区间。可以用info break查看断点信息?/p>
如果不想删除断点Q只是想暂时使它失效Q则可以使用disable命o。disable命o的Ş式如下:
a)disable [breakpoints] [ range ...]
使指定区?range 内的断点失效。如果不指定 range Q则所有的断点都失效?/p>
使断点生效的命o是enableQŞ式有Q?/p>
a)enable [breakpoints] [ range ...]
使指定区?range 内的断点或者所有断点生效?/p>
b)enable [breakpoints] once range...
使指定区间内的断点生效一ơ?/p>
c)enable [breakpoints] delete range...
使指定区间内的断点生效一ơ,然后删除?/p>
断点条g使得只有在相应的条g满Ӟ断点才有效。这里的条g表达式跟E序所用语a的逻辑表达式的语法相同Q例如在c/c++语言里,可以?a==b 或?x&&yq种表达式?/p>
断点条g可以在设|断点的时候指定,也可以在断点讄后通过condition命o来设|或者改变?condition的Ş式ؓQ?/p>
a)condition bnum expression
讄表达?expression 为停止点 bnum 的条件?/p>
b)condition bnum
删除停止?bnum 的条件?/p>
q有一个命令,可以使得gdb忽略断点的条件一定的ơ数Q其形式为:
a)ingore bnum count
许多gdb命o都接受一个用于指定程序位|的参数。位|的指定方式有下面几U:
a) linenum
当前源文件的行号?/p>
b) -offset
当前行前面,跟当前行间隔?offset 的行。当前行可以q样定Q用list命oQ打印出来的最后一行就是当前行Q或者对于断点命令,选定的栈帧中Q程序停止执行的位置是当前行?/p>
c) +offset
当前行后面,跟当前行间隔?offset 的行?/p>
d) filename:linenum
源文?filename 中的?linenum?/p>
e) function
当前源文件中的函?function?/p>
f) filename:function
源文?filename 中的函数 function?/p>
g) * address
指定E序地址 address。常用的 address 形式有:
expression Q- 当前语言中有效的表达式?/p>
funcaddr Q- 函数的地址。在c/c++中就是函数名?/p>
'filename'::funcaddr Q- 源文?filename 中的函数地址 funcaddr?/p>
后面懒得写了Q暂时先放一放。发现就是抄文档,内容多了也是个很累h的活。唉Q懒了,不行?..
待添?/p>
待添?/p>
待添?/p>
q篇文章只是捡了GDB中最常用的一些东西,而且q只是最常用的东西中的一部分,有兴或者需要的可以直接看GDB的文档,可以?a >q里扑ֈ?/p>
1. 不知道是不是因ؓwindows和linuxpȝ的不同,用gdb启动E序后,执行show paths后输出:Executables and object file path: 。也是说输出的值是I的?/p>
The big cat ate the small catfish
存在(两次),但是不在字符串S2 = Dogs for sale?一直觉得source insight中显C变量和函数定义的context window很好,昨天H然发现原来ecb(Emacs Code Browser)中也有个cM的东?当layout换成left_symboldef?左下H口是?啥也不说?贴个囑.
q个是我Ҏ原先的layout
left_symboldef改的.可以看到左边那一?上面是函数啥的列?下面是W号定义H口.有两点不爽的是符号定义窗口没法单独放在下?主要是放在左边的?函数原型比较长的没法完整显C?二是不能像si那样双击跌{.不过也不错了,跌{用cscope也容?
ps:我的ecb函数列表中没法显C参数类?哪位如果知道ȝ说一下哈,谢了!
0. 序曲
写这短文的起因?前两天想d大的acm在线pȝ扑և道题做做。ؓ什么呢?因ؓ本h天大毕业,q个天大呢可是中国最早的大学,原名北洋大学?q可l对是货真h实的W一所大学。给大家推荐推荐?学风那是相当的好?/p>
扯多?q是回到本来的话题上。上了acmpȝ之后,先看了1001。那道题的意思是输入一些正整数(以EOFl束),把对应的字符输出。这个简?E序很快出来了:
#include <stdio.h>
int main()
{
int c;
while(scanf("%d", &c) != EOF)
{
putchar(c);
}
return 0;
}
E序q行,输入103 102 105 107<enter>
输出gfik?/p>
当时q行完之后马上想,Z么不是输入一个数字马上输Z个字W呢,因ؓ看程序确实是q样的逻辑,只要不是EOF,׃输出。又一?对了,是缓冲的问题。想hAPUE里边说得stdin应该是行~冲?另外,可以用setbuf,setvbuf讑֮的~冲。于是想stdin设成无缓冲的。于是程序变成这?
#include <stdio.h>
int main()
{
int c;
setbuf(stdin, NULL);
while(scanf("%d", &c) != EOF)
{
putchar(c);
}
return 0;
}
可是~译q行,q是老样?没有变化。想了想,没想出是啥原?于是开始google和APUE。终于算是明白了?整理在这ѝ?/p>
声明Q?/p>
本文很大部分内容来自APUEQ-UNIX环境高~程?/p>
1. ~冲cd?/p>
标准库提供缓冲是Z减少对read和write的调用。提供的~冲有三U类?整理自APUE):
在这U情况下,实际的I/O操作只有在缓冲区被填满了之后才会q行。对ȝ在磁盘上的文件的操作一般是有标准I/O库提供全~冲。缓冲区一般是在第一ơ对进行I/O操作?由标准I/O函数调用malloc函数分配得到的?/p>
术语flush描述了标准I/O~冲的写操作。缓冲区可以由标准I/O函数自动flush(例如~冲区满的时?;或者我们对调用fflush函数?/p>
在这U情况下,只有在输?输出中遇到换行符的时?才会执行实际的I/O操作。这允许我们一ơ写一个字W?但是只有在写完一行之后才做I/O操作。一般的,涉及到终端的?-例如标注输入(stdin)和标准输?stdout)--是行~冲的?/p>
标准I/O库不~存字符?span style="color: #ff0000;">需要注意的?标准库不~存q不意味着操作pȝ或者设备驱动不~存?br>
ISO C要求:
但是,qƈ没有告诉我们当标准输?输出在涉及交互设备时,它们是无~存的还是行~存?也没有告诉我们标准错误应该是行缓存的q是无缓存的。不q?大多数实现默认的~存cd是这L:
2. 改变默认~存cd
可以通过下面的函数改变缓存类?摘自APUE):
void setbuf(FILE *restrict fp, char *restrict buf);
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
q些函数必须在流打开之后、但是未Ҏ做Q何操作之前被调用(因ؓ每个函数都需要一个有效的文g指针作ؓW一个参??/span>
利用setbufQ可以打开或者关闭缓存。ؓ了打开~存Qbuf参数必须一个大ؓBUFSIZ的缓存,BUFSIZ是定义在stdio。h中的帔R?amp;amp;lt;&lt;ISO/IEC 9899&gt;&gt;要求QBUFSIZ臛_?56。如果要关闭~存Q可以将buf设成NULL?/span>
利用setvbufQ我们可以设定缓存类型。这是通过mode参数指定的?/span>
关于q两个函敎ͼ可以看下表(摘自APUEQ:
Function |
mode |
buf |
Buffer and length |
Type of buffering |
---|---|---|---|---|
setbuf |
non-null |
user buf of length BUFSIZ |
fully buffered or line buffered |
|
NULL |
(no buffer) |
unbuffered |
||
setvbuf |
_IOLBF |
non-null |
user buf of length size |
fully buffered |
NULL |
system buffer of appropriate length |
|||
_IOFBF |
non-null |
user buf of length size |
line buffered |
|
NULL |
system buffer of appropriate length |
|||
_IONBF |
(ignored) |
(no buffer) |
unbuffered |
需要注意的是:如果在函数内为流分配了自动变量作为缓存,那么在退Z前需要将关闭。因此最好让pȝ自己分配~存Q这些缓存在关闭的时候会自动被释放?/span>
3.如果清理输入~存
关于q点可以参看comp.lang.c FAQ的Question12.26b:
Q: If fflush won't work, what can I use to flush input?
A: It depends on what you're trying to do. If you're trying to get rid of an unread newline or other unexpected input after calling scanf (see questions 12.18a-12.19), you really need to rewrite or replace the call to scanf (see question 12.20). Alternatively, you can consume the rest of a partially-read line with a simple code fragment like
while((c = getchar()) != '\n' && c != EOF)
/* discard */ ;
(You may also be able to use the curses flushinp function.)
There is no standard way to discard unread characters from a stdio input stream. Some vendors do implement fflush so that fflush(stdin) discards unread characters, although portable programs cannot depend on this. (Some versions of the stdio library implement fpurge or fabort calls which do the same thing, but these aren't standard, either.) Note, too, that flushing stdio input buffers is not necessarily sufficient: unread characters can also accumulate in other, OS-level input buffers. If you're trying to actively discard input (perhaps in anticipation of issuing an unexpected prompt to confirm a destructive action, for which an accidentally-typed ``y'' could be disastrous), you'll have to use a system-specific technique to detect the presence of typed-ahead input; see questions 19.1 and 19.2. Keep in mind that users can become frustrated if you discard input that happened to be typed too quickly.
References: ISO Sec. 7.9.5.2
H&S Sec. 15.24. 几点需要注意的地方
setbuf() has to do with the delivery of bytes between the
C library FILE* management layer and the OS I/O layer.Calls to fread(), fgets(), fgetc(), and getchar() work within
whatever FILE* buffered data is available, and when that data
is exhausted, the calls request that the FILE* buffer be refilled
by the system I/O layer.When full buffering is turned on, that refill operation results in the
FILE* layer requesting that the operating system hand it a full
buffer's worth of data; when buffering is turned off, that
refill operation results in the FILE* layer requesting that the
operating system return a single character....setting an input stream to be unbuffered
does NOT tell the operating system to tell the device driver
to go into any kind of "raw" single-character mode. There are
system-specific calls such as ioctl() and tcsetterm() that
control what the device driver will do.
当然Q单U用来编辑文件的话还是vim方便一些,毕竟vim区分模式Q有些操作可以用很少的按键快速的完成?/p>
不知道emacs的宏录制功能如何。感觉vim里面的宏真的是太好用了,弄得我很是舍不得vim。要是有个编辑器能集合vim的高效快捯emacs的强大扩展能力就好了?/p>
http://www.shnenglu.com/lucency/services/metaweblog.aspx
google blog api
http://www.blogger.com:80/feeds/default/blogs