C

共 58 篇文章。

一个奇怪的移位计算结果

• Development

今天 强迫症 朱小瘦同学提到一个非常有意思的问题,一个32bit的无符号整数算术右移32个bit应该得多少?

我们知道算术右移一个bit相当于除2,所以一个32bit无符号整数除以 2322^{32},理论上,应该得0。

然而事实不是这样。测试显示在 x86 系统上,一个32bit无符号整数算术右移32个bit之后得到的是原数。例如下面这个测试程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>

int
main(void /* int argc, char **argv */)
{
	unsigned int a = 0x5a5a5a5a;

	a >>= 32;

	printf("%x\n", a);

	return 0;
}

不启用任何优化的话,编译出来的程序得到的结果是:

5a5a5a5a

更进一步,我们将上面的测试改写为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>

int
main(void /* int argc, char **argv */)
{
	unsigned int a = 0x5a5a5a5a;
	int i;

	for (i=0; i<33; i++)
		printf("%x\n", a >> i);

	return 0;
}
阅读全文… ( 本文约 881 字,阅读大致需要 2 分钟 )

sizeof(void *)和sizeof(int(*)(void))

• Development

以前一直没注意过这个问题,今天在邮件列表看到 Matthew Flemming 发的邮件才知道实际上 C 标准并不保证 sizeof(void *) == sizeof(int(*)(void))。不过,几乎所有的现代系统上这个等式都是成立的。

阅读全文… ( 本文约 180 字,阅读大致需要 1 分钟 )

对齐操作和非对齐操作

• Kernel

操作是否对齐是一个简单而容易忽略的性能(有时是可靠性)问题。对齐主要是指读写操作不产生不必要地跨越存储设备上原生存储单元的访问,这里的存储单元说的是在访问路径上的任何设备,它可以是外存,也可以是内存,甚至是CPU附近或内建的快取缓存,等等。

阅读全文… ( 本文约 1145 字,阅读大致需要 3 分钟 )

为什么重复free()比内存泄漏危害更大

• Security

C程序设计中,内存操作相关的错误可以说是最常见,同时也是非常隐蔽的一类错误。这类错误往往导致程序莫名其妙地崩溃、耗尽系统资源,或是形成严重的安全弱点。

阅读全文… ( 本文约 1142 字,阅读大致需要 3 分钟 )

NULL指针引用和内核bug的利用

• Security

总算是发公告了,可以说具体的事情了。

FreeBSD昨天发布了2项安全公告和1项Errata Notice:SA-09:13.pipe、SA-09:14.devfs和EN-09:05.null。两个安全公告修正的是同一类问题,也就是我们常说的多线程程序中的竞态条件(Race Condition);EN-09:05.null则是增加了一个使这类问题不再那么容易被利用达到特权提升目的的功能,但默认并不启用。

阅读全文… ( 本文约 1197 字,阅读大致需要 3 分钟 )

为什么FreeBSD没有CIRCLEQ_*

• Development

最近在看 Berkeley DB,发现一套 FreeBSD 上没有的宏, CIRCLEQ_*。

看了一下,这组宏是来自 4.4BSD 的,因此 FreeBSD 曾经有过这个宏;后来, phk 在 2000 年 12 月 29 日从 FreeBSD 里面把它拿掉了(SVN revision 70469),当时的说明如下:

阅读全文… ( 本文约 324 字,阅读大致需要 1 分钟 )

fgetc()返回值是int而不是char

• Development

其实是个很简单的常识,居然搞了我半个小时……

fgetc()的返回值是int,因为这个值除了返回拿到的字符之外,还兼作错误标志。由于fgetc()允许文件中包含任意内容,所以只好增大返回值的宽度来表达。

阅读全文… ( 本文约 135 字,阅读大致需要 1 分钟 )

memchr(3) rewrite

• Development

I have taken some time to rewrite memchr(3) to utilize similiar algorithm as my strlen(3) did. Two different formular, however, would have a roughly 1/3 difference.

Currently I have taken an approach that when memchr(3) is trying to match a pattern of 8-bit, then consider the string as 8-bit, which uses the first formular which is expected to have uniform O(n) time complexity by reducing unnecessary branches.

This approach, however, might be bogus since if you find 7-bit character within a 8-bit string, in that case, memchr(3) would perform poorly, if there are a lot of characters having their MSB as 1.

阅读全文… ( 本文约 114 字,阅读大致需要 1 分钟 )

New strlen(3) committed

• Development

Finally, I got my strlen(3) [1] committed against -HEAD. This is a long story, to put it short, I had proposed assembly version of some string operations at the point of 2005, but these was never committed due to a hard disk failure, and as Bruce pointed out, having the hand optimized assembly code use a different algorithm is not good in general.

Therefore, I have take some time on it and reimplemented the idea in C, resulting in a portable (say, you can use it on any 32-bit or 64-bit processors, and it can be easily extended to 128-bit) version.

So, is it important for *YOU*?

Generally speaking, it should not. Performance sensitive programs should, by all means, avoid C style string operations. Think a 5x better strlen(3) would boost performance of your application since it uses strlen(3) in critical path? Think again!

However, I found it valuable. There is difference in worldstone, where I saw some minor improvements. Micro-benchmark indicates that this version is at most 2x slower when the string is very short, but 5x faster for strings that is at least word-length long.

[1] Note: the version has been further revised to provide better comment and match style(9).

阅读全文… ( 本文约 295 字,阅读大致需要 2 分钟 )