文章目录

最近在学习Linux C 编程,碰到一个关于write系统调用的疑问。

程序1:

1
2
3
4
5
6
7
8
#include <unistd.h>
#include <stdlib.h>

int main() {
if ((write(1, "Here is some data\n", 18)) != 18)
write(2, "A error has occured on file descriptior 1\n", 42);
exit(0);
}

编译后在终端中运行,运行结果如下:

1
Here is some data

如果稍微改变一下write的实参值,将第一个write函数的第三个参数改为17,运行结果如下:

1
Here is some data A error has occured on file descriptior 1

将18改为20,在终端中运行的结果如下:

1
Here is some data
A error has occured on file descriptior 1

此程序没有疑问。

程序2:

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

int main() {
int nb;
nb = (int)write(1, "Here is some\n", 18);
if (nb != 18)
write(2, "A error has occured on file descriptior 1\n", 42);
printf("\nThe value returned by the function write is %d\n", nb);
exit(0);
}

编译运行后的结果如下:

1
Here is some
A
The value returned by function write is 18

程序2运行后,第二行为什么会输出一个A ? 这个A明显是if语句块里的那个write函数的结果。如果nb的值确实是18,那么按理来说,if语句就不会执行,就不会有这个A;如果nb的值不是18,那么按理第二行应该输出:

1
A error has occured on file descriptior 1\n

原因分析如下:

常量字符串按顺序存储在常量区域的。

1
"Here is some\n"
"A error has occured on file descriptior 1\n"

这两个常量字符串的地址是紧挨着的, 当第一个字符串的访问越界后就访问到第二个字符串了。

考虑下对齐,指针的地址通常需要是 32 位对齐,也就是 4 的倍数。所以前面的 14 个字符会被多填充两个 0 来对齐到 16 个字节,在加上后面的 A 和一个空格, 刚好 18 个。

文章目录
Fork me on GitHub