yaron's space
以技术为主
以技术为主
二 12th
gdb提供awtach rwatch watch来监控调试中变量或者内存的变化
awatch 命令
awtach [expr]
当debugger read或者write该expr时,debugger 停止
rwatch 命令
rwatch [expr]
当debugger read该expr时,debugger停止
watch命令
watch [expr]
当debugger write该expr时,debugger停止
说明:expr可以是变量或者是内存地址
十二 22nd
笔者在本博客上之前记录了vim相关方面的用法,现在总结下,记录的文章如下:
2. Vim纵向编辑模式的用法
4. vim中两个实用插件doxygen和projects的安装与使用
5. VIM查找替换归纳总结
6. vim编辑多个文件的方法
十 17th
昨天笔试遇到了关于c++中关于const与const_cast的题目,大概如下:
int main(int argc, char* argv[]) { const int a = 10; int * p = const_cast<int *>(&a); *p = 1; printf("%d %d\n", a, *p); return 0; }
求上述程序的输出结果,正确答案是:10 1
首先可以确定是p和&a的地址是指向同一片内存区域的,理论上来说最后的输出结果应该是1 1
但是为什么会输出a的值为10呢? 猜测应该是const关键字的问题,可能编译器看到a为const型变量,所以在编译期就将所有的a直接替换为10了,这个是编译器做的一个优化,
下面简单的验证下:
直接使用下面的命令来看下编译后的汇编代码,关键部分的汇编如下:
movl %edi, -20(%rbp) movq %rsi, -32(%rbp) movl $10, -12(%rbp) leaq -12(%rbp), %rax movq %rax, -8(%rbp) movq -8(%rbp), %rax movl $1, (%rax) movq -8(%rbp), %rax movl (%rax), %edx movl $10, %esi movl $.LC0, %edi movl $0, %eax call printf movl $0, %eax leave ret
显然%rax中存放的指针p的值,(%rax)代表间接寻址
在调用printf函数之前,将10放入%esi, (%rax)放入到%edx中,显然验证了上述的猜想
如何避免编译器做这方面的优化呢?
一个常用的方法是将变量a加上关键字volatile,代表是”易变,每次都需要从内存中读取,这样上述程序的运行结果就是1 1了
当然修改常量变量的值不是好的编程习惯,尽量还是少用上述用法
十 8th
如果单纯地使用sort按行进行排序比较简单,
但是使用sort按多个列值排列,同时使用tab作为分隔符,而且对于某些列需要进行逆序排列,这样sort命令写起来就比较麻烦了
比如下面的文件内容,使用[TAB]进行分割:
Group-ID Category-ID Text Frequency ---------------------------------------------- 200 1000 oranges 10 200 900 bananas 5 200 1000 pears 8 200 1000 lemons 10 200 900 figs 4 190 700 grapes 17
下面使用这些列进行排序(列4在列3之前进行排序,而且列4是逆序排列)
* Group ID (integer)
* Category ID (integer)
* Frequency “sorted in reverse order” (integer)
* Text (alpha-numeric)
排序后的结果应该为:
Group-ID Category-ID Text Frequency ---------------------------------------------- 190 700 grapes 17 200 900 bananas 5 200 900 figs 4 200 1000 lemons 10 200 1000 oranges 10 200 1000 pears 8
可以直接使用sort命令来解决这个问题:
sort -t $'\t' -k 1n,1 -k 2n,2 -k4rn,4 -k3,3 <my-file>
解释如下:
-t $'\t':指定TAB为分隔符 -k 1, 1: 按照第一列的值进行排序,如果只有一个1的话,相当于告诉sort从第一列开始直接到行尾排列 n:代表是数字顺序,默认情况下市字典序,如10<2 r: reverse 逆序排列,默认情况下市正序排列
所以最后的命令:sort -t $'\t' -k 1n,1 -k 2n,2 -k4rn,4 -k3,3 my-file
十 6th
原文地址:register、volatile、restrict 三关键字的用法 – RaymondAmos的技术专栏 – CSDN博客.
register
使用修饰符register声明的变量属于寄存器存储类型。该类型与自动存储类型相似,具有自动存储时期、代码块作用域和内连接。声明为register 仅仅是一个请求,因此该变量仍然可能是普通的自动变量。无论哪种情况,用register修饰的变量都无法获取地址。如果没有被初始化,它的值是未定的。
volatile
volatile告诉编译器该被变量除了可被程序修改外,还可能被其他代理、线程修改。因此,当使用volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,而不使用寄存器中的缓存的值。比如,
val1=x; val2=x;
如 果没有声明volatile,系统在给val2赋值的时候可能直接从寄存器读取x,而不是从内存的初始位置读取。那么在两次赋值之间,x完全有可能被被某 些编译器未知的因素更改(比如:操作系统、硬件或者其它线程等)。如果声明为volatile,编译器将不使用缓存,而是每次都从内存重新读取x。
restrict
restrict是c99引入的,它只可以用于限定指针,并表明指针是访问一个数据对象的唯一且初始的方式,考虑下面的例子:
int ar[10]; int * restrict restar=(int *)malloc(10*sizeof(int)); int *par=ar;
这里说明restar是访问由malloc()分配的内存的唯一且初始的方式。par就不是了。那么:
for(n=0;n<10;n++) { par[n]+=5; restar[n]+=5; ar[n]*=2; par[n]+=3; restar[n]+=3; }
因 为restar是访问分配的内存的唯一且初始的方式,那么编译器可以将上述对restar的操作进行优化:restar[n]+=8;。而par并不是访 问数组ar的唯一方式,因此并不能进行下面的优化:par[n]+=8;。因为在par[n]+=3前,ar[n]*=2进行了改变。使用了关键字 restric,编译器就可以放心地进行优化了。这个关键字据说来源于古老的FORTRAN。
总结
两个关键字:volatile和restrict,两者都是为了方便编译器的优化。
九 25th
两道的题目:
1. dup(int fd)和dup2(int fd1, int fd2)函数的区别:详细请见http://blog.donews.com/mutecat/archive/2007/09/20/1212178.aspx
2. 有关一致性哈希的算法设计
其他的是 多项选择题目,涉及的范围比较广,linux和语言层次的题目偏多一些吧
包括堆栈缓冲区溢出以及linux内核中container_of宏的实现,以及spinlock和虚拟内存的相关知识
关于container_of这个请参考我的前一篇blog: http://yaronspace.cn/blog/index.php/archives/1026
八 26th
最近客户端连debian下sshd很慢,每次都需要等待半分钟左右,今天终于无法忍受了,上网找了下资料,把这个问题解决了
原因:
主要是debian在默认情况下开启了dns的反向解析,这个比较耗时
解决方法:
1. 编辑/etc/nsswitch.conf 找到hosts行,替换为
hosts: files dns [NOTFOUND=return]
2. 查看/etc/resolv.conf文件,查看dns地址是否设置正确,如果没有用,直接注掉即可
3. 重启sshd : 先kill掉,然后/usr/sbin/sshd 启功即可
近期评论