c - 为什么 opendir() 会更改传递给它的文件路径字符串?
问题描述
我正在尝试编写一个给定当前工作目录的函数,它将打印该目录的所有内容以及 cwd 中子目录中的内容。
void printDir(char *cwd)
{
printf("file path after printdir call: %s\n",cwd);
DIR *dirPtr = opendir(cwd);
struct dirent *dirEnt;
char *slash = "/";
char *dot = ".";
char *dotdot = "..";
char *pathPrefix = malloc(sizeof(cwd) + sizeof(slash)+1);
pathPrefix = strcat(cwd,slash);
if (dirPtr != NULL)
{
while((dirEnt = readdir(dirPtr)) != NULL)
{
char *temp = dirEnt->d_name;
if (strcmp(temp,dot) != 0 && strcmp(temp,dotdot) != 0)
{
char *tempFullPath = malloc(sizeof(pathPrefix) + sizeof(temp) + 1);
tempFullPath = strcpy(tempFullPath, cwd);
strcat(tempFullPath, temp);
printf("file path before we try to openthedir: %s\n",tempFullPath);
DIR *tempSubDirPtr = opendir(tempFullPath);
printf("filePath after we try to open this shit: %s\n",tempFullPath2);
if (tempSubDirPtr != NULL)
{
printf("file path right before a recursive call: %s\n",tempFullPath);
closedir(tempSubDirPtr);
printDir(tempFullPath);
}
printf("%s\n",tempFullPath);
}
}
}
else
{
使用调试 printf() 的控制台输出是:
current working directory string after getcwd: /home/TTU/canorman/testUtil
file path after printdir call: /home/TTU/canorman/testUtil
file path before we try to openthedir: /home/TTU/canorman/testUtil/find.c
filePath after we try to open this shit: /home/TTU/canorman/testUtil/find.c
/home/TTU/canorman/testUtil/find.c
file path before we try to openthedir: /home/TTU/canorman/testUtil/find2.c
filePath after we try to open this shit: /home/TTU/canorman/testUtil/find2.c
/home/TTU/canorman/testUtil/find2.c
file path before we try to openthedir: /home/TTU/canorman/testUtil/find
filePath after we try to open this shit: /home/TTU/canorman/testUtil/find
/home/TTU/canorman/testUtil/find
file path before we try to openthedir: /home/TTU/canorman/testUtil/testDir
filePath after we try to open this shit: /home/TTU/canorman/testUA
file path right before a recursive call: /home/TTU/canorman/testUA
file path after printdir call: /home/TTU/canorman/testUA
Could not open specified working directory
/home/TTU/canorman/testUA/
因此,您可以在输出的最后几行中看到文件字符串来自
/home/TTU/canorman/testUtil/testDir
至
/home/TTU/canorman/testUA
我在 opendir(3) 手册页中找不到任何关于这种情况的信息。关于为什么会这样的任何想法。
解决方案
这段代码肯定是错误的:
char *pathPrefix = malloc(sizeof(cwd) + sizeof(slash)+1);
pathPrefix = strcat(cwd,slash);
正如@Steve 和@William 所指出的,sizeof
它们应用于指针而不是字符串,因此它每个分配4 或8 个字节(加一个),这不太可能是足够的。strlen(s)
计算字符串中活动字符的数量;您必须自己为 NUL 字节添加 +1。
但更大的问题是使用strcat()
,它将第二个字符串附加到第一个字符串的尾部,修改第一个字符串。这不是为您创建新的连接字符串,而是将其填充到新分配的(太小)内存中。
这应该表现得更好:
char *pathPrefix = malloc(strlen(cwd) + strlen(slash) + 1);
strcpy(pathPrefix, cwd); // cwd goes to the start of the new buffer
strcat(pathPrefix, slash); // append the slash to the end of cwd
...然后在其余代码中进行类似的更改。
编辑:在进行此类工作时,最好对您不打算修改的const
任何变量进行限定(从您的角度来看,字符串是只读的)。char *
这样做会为您的代码添加有用的文档,并且编译器会警告您常见的错误。
例子:
void printDir(const char *cwd)
{
...
const char *slash = "/";
const char *dot = ".";
const char *dotdot = "..";
...
无论如何修改字符串文字都是不合法的,但如果cwd
参数是 const 限定的,编译器会反对,strcat(cwd, slash)
因为它知道第一个参数被写入。
这并没有真正改变代码的行为,但这是一个养成的好习惯。const
是你的朋友。
推荐阅读
- python - 需要创建一个函数 cumsum 来返回一个列表 l 的累积和
- amazon-web-services - Lambda 安全组到 S3 和 Secrets Manager
- python - 在服务器上找不到请求的 URL。如果您手动输入了 URL,请检查您的拼写并重试。烧瓶
- html - 如何将样式添加到 base.html:Django 框架?
- python - 如何在 python 中使用 opencv 将视频的特定部分保存到单独的视频中?
- php - How to display errors for invalid login?
- angular - 检测窗口何时滚动超过Angular中的div
- node.js - 多对多关系 mongoose 与 oauth 护照作为数据库 node.js 待办事项
- python - Python字典迭代问题
- javascript - 在reactjs中将我的数据发送到后端时无法获得响应