C - 调用 getcwd 是否导致此处出现错误?
C - is calling getcwd causing a bug here?
我正在学习 stat 和 readlink 等系统调用。我尝试以两种不同的方式统计根目录:
- 只需统计 root 的路径。简单。
- 然后,一个迂回的方式,fopen“/”,从我得到的fd创建一个文件描述符路径,并读取链接它以获得“/”。然后统计
我不明白的是这按我预期的方式工作并且 inode 编号相同,除非我在之后引入更多代码,即 getcwd,奇怪的是 inode 不一样并且测试 2 失败。如果你 运行 两个版本,有和没有它说要删掉的部分,p2 的 printf 也会改变,你可以看到 /
之后有垃圾。我在这里做错了什么或这里发生了什么?这些初始语句之后的代码如何导致代码中较早的更改?
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
int main()
{
/* Stat root this way */
struct stat st1;
char *p1 = "/";
if (!stat(p1, &st1))
printf("PASS\n");
else
printf("FAIL - %m\n");
/* Stat root another way */
struct stat st2;
char fdpath[100], p2[100];
FILE *fp = fopen("/", "r");
sprintf(fdpath, "/proc/self/fd/%d", fileno(fp));
readlink(fdpath, p2, sizeof(p2));
if (!stat(p2, &st2))
printf("PASS\n");
else
printf("FAIL - %m\n");
printf("p2 = %s\n", p2);
/* Check inodes are the same */
printf(" st1.st_ino = %ld\n", st1.st_ino);
printf(" st2.st_ino = %ld\n", st2.st_ino);
/* TRY WITHOUT THIS - Adding this makes the inodes different! Take it out and they're the same */
char cwd_buf[100];
char *cwd_ret = getcwd(cwd_buf, sizeof(cwd_buf));
if (cwd_ret == NULL)
printf("getcwd failed - %m\n");
printf("cwd_ret = %s\n", cwd_ret);
return 0;
}
来自联机帮助页:
readlink() places the contents of the symbolic link pathname in the buffer buf, which has size bufsiz. readlink() does not append a null byte to buf. It will (silently) truncate the contents (to a length of bufsiz characters), in case the buffer is too small to hold all of the contents.
因此,如果要将 p2
用作字符串,则需要手动执行此操作:
int size = readlink(fdpath, p2, sizeof(p2) - 1);
if (size < 0)
{
// error
}
p2[size] = 0;
注意 -1:即使字符串被截断,它也应该为空终止符保留一个字节。
readlink
不会以 null 终止它 returns 的字符串,因此 p2
可能在 /
.
之后包含任意垃圾
你应该做
ssize_t len = readlink(fdpath, p2, sizeof(p2));
if (len == -1) { /* error */ }
if (len == sizeof(p2)) { /* truncated */ }
p2[len] = '[=10=]';
if (!stat(p2, &st2)) // ...
你也应该在许多其他地方进行错误检查。
在最后添加和删除不相关的代码可能改变了堆栈布局(因为额外的局部变量),这意味着 p2
包含 不同 垃圾和没有它。甚至在某些情况下,垃圾是空字节,因此字符串最终恰好被正确终止。这种事情经常发生在 C 代码中的错误中,并不是特别有意义;它是 C 标准语言中的未定义行为。不要想太多为什么会发生;试着找出并修复错误,不要再写同样的错误:-)
我正在学习 stat 和 readlink 等系统调用。我尝试以两种不同的方式统计根目录:
- 只需统计 root 的路径。简单。
- 然后,一个迂回的方式,fopen“/”,从我得到的fd创建一个文件描述符路径,并读取链接它以获得“/”。然后统计
我不明白的是这按我预期的方式工作并且 inode 编号相同,除非我在之后引入更多代码,即 getcwd,奇怪的是 inode 不一样并且测试 2 失败。如果你 运行 两个版本,有和没有它说要删掉的部分,p2 的 printf 也会改变,你可以看到 /
之后有垃圾。我在这里做错了什么或这里发生了什么?这些初始语句之后的代码如何导致代码中较早的更改?
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
int main()
{
/* Stat root this way */
struct stat st1;
char *p1 = "/";
if (!stat(p1, &st1))
printf("PASS\n");
else
printf("FAIL - %m\n");
/* Stat root another way */
struct stat st2;
char fdpath[100], p2[100];
FILE *fp = fopen("/", "r");
sprintf(fdpath, "/proc/self/fd/%d", fileno(fp));
readlink(fdpath, p2, sizeof(p2));
if (!stat(p2, &st2))
printf("PASS\n");
else
printf("FAIL - %m\n");
printf("p2 = %s\n", p2);
/* Check inodes are the same */
printf(" st1.st_ino = %ld\n", st1.st_ino);
printf(" st2.st_ino = %ld\n", st2.st_ino);
/* TRY WITHOUT THIS - Adding this makes the inodes different! Take it out and they're the same */
char cwd_buf[100];
char *cwd_ret = getcwd(cwd_buf, sizeof(cwd_buf));
if (cwd_ret == NULL)
printf("getcwd failed - %m\n");
printf("cwd_ret = %s\n", cwd_ret);
return 0;
}
来自联机帮助页:
readlink() places the contents of the symbolic link pathname in the buffer buf, which has size bufsiz. readlink() does not append a null byte to buf. It will (silently) truncate the contents (to a length of bufsiz characters), in case the buffer is too small to hold all of the contents.
因此,如果要将 p2
用作字符串,则需要手动执行此操作:
int size = readlink(fdpath, p2, sizeof(p2) - 1);
if (size < 0)
{
// error
}
p2[size] = 0;
注意 -1:即使字符串被截断,它也应该为空终止符保留一个字节。
readlink
不会以 null 终止它 returns 的字符串,因此 p2
可能在 /
.
你应该做
ssize_t len = readlink(fdpath, p2, sizeof(p2));
if (len == -1) { /* error */ }
if (len == sizeof(p2)) { /* truncated */ }
p2[len] = '[=10=]';
if (!stat(p2, &st2)) // ...
你也应该在许多其他地方进行错误检查。
在最后添加和删除不相关的代码可能改变了堆栈布局(因为额外的局部变量),这意味着 p2
包含 不同 垃圾和没有它。甚至在某些情况下,垃圾是空字节,因此字符串最终恰好被正确终止。这种事情经常发生在 C 代码中的错误中,并不是特别有意义;它是 C 标准语言中的未定义行为。不要想太多为什么会发生;试着找出并修复错误,不要再写同样的错误:-)