0

我找到了从这里获取当前工作目录的 C 代码片段。本质上,代码是:

char directory[_MAX_PATH];
getcwd(directory, sizeof(directory))

我想将它抽象到另一个函数中,在不同的文件中(因此如果需要,它可以在不同的平台上换出)。

目前,我在外部文件中

void getCurrentDirectory(char *directory) {
    getcwd(directory, sizeof(directory));
}

并在主文件中

char directory[100];
getCurrentDirectory(directory);
printf("%s", *directory);

但是,当打印到屏幕时,我会胡说八道(可能试图将内存位置打印为字符串?)

我敢肯定,这对于非初学者来说是显而易见的。这是怎么回事?

编辑:我在 Windows 7 上,顺便说一句

谢谢。

4

8 回答 8

2

您将 char* 的大小传递给 getcwd,而不是数组的大小。

将大小参数传递给您的函数。

void getCurrentDirectory(char *directory, size_t size) {
    getcwd(directory, size);
}

接着:

char directory[100];
getCurrentDirectory(directory, sizeof(directory));
printf("%s", *directory);

此外,如果您使用的是 Windows,您可能应该将数组大小更改为预定义的大小MAX_PATH以避免潜在的缓冲区溢出。getcwd 需要一个长度,但我不认为所有的文件函数都这样做。

于 2011-05-23T15:57:17.827 回答
2

这一行: printf("%s", *directory);

应该: printf("%s", directory);

您将第一个元素(目录 [0])传递给 printf,而不是指向 char 数组的指针。

于 2011-05-23T15:58:08.753 回答
2

如果是 C++,我建议尽可能使用boost::filesystem,它隐藏了所有底层平台细节为您提供 C++ 风格的界面,而不是缓冲区容易溢出的 C 函数。

于 2011-05-23T15:58:49.593 回答
2

您在这里做错了很多事情:

void getCurrentDirectory(char *directory) 
  {
      getcwd(directory, sizeof(directory));
  }

错误一:

`sizeof(directory)` 

给你一个指针的大小,准确地说是char *。您的意图是传递数组的大小,而不是指针大小。

错误2:

`printf("%s", *directory);` 

将数组的第一个元素传递给 printf,而不是数组的地址。您的意图是打印整个数组,而不仅仅是第一个元素。

更正的解决方案

你应该做

void getCurrentDirectory(char *directory, size_t arrSize)  
{                                         ^^^^^^^^^^^^^^
    getcwd(directory, arrSize);
}

数组的大小是显式传递的,因此函数可以使用它。

在主要同时打印数组的内容:

   printf("%s", directory);
于 2011-05-23T15:58:56.007 回答
1

您应该在本地分配缓冲区(已知必要的长度,并且需要知道实际长度)并返回一个字符串:

std::string
getCurrentDirectory()
{
    char results[_MAX_PATH];
    if ( getcwd( results, sizeof(results) ) == NULL )
        throw std::ios_base::failure( "Could not get current directory" );
    return std::string( results );
}

还要注意,这_MAX_PATH只是一个猜测;实际最大值不是编译时间常数(因为它取决于文件系统)。考虑到这一点的实现可能类似于:

std::string
getCurrentDirectory()
{
    long length = pathconf( ".", _PC_PATH_MAX );
    if ( length == -1 )
        throw std::ios_base::failure(
                "Could not determine necessary buffer length to get current directory" );
    std::string results( length, '\0' );
    if ( getcwd( &results[0], results.size() ) == NULL )
        throw std::ios_base::failure( "Could not get current directory" );
    results.resize( strlen( results.c_str() );
    return results;
}

但是,如果该程序仅用于没有 NFS 或 SMB 安装驱动器的个人系统上,这可能是矫枉过正。

于 2011-05-23T16:10:43.720 回答
1

既然是 C++,为什么不这样做:

std::string getCurrentDirectory()
{
    char directory[_MAX_PATH] = {};
    getcwd(directory, sizeof(directory));
    return directory;
}
于 2011-05-23T16:10:50.083 回答
0

现在回答你的问题:

当 getcwd 由于某种原因失败时,(在您的情况下)指向的数组的内容directory是未定义的。因此,在您的错误实现中,大多数情况下您会看到垃圾。(另外,你应该检查返回值getcwd,失败时返回-1)

现在,在您的情况下失败的原因是您指定使用sizeof(directory)的大小只是指针的大小(可能是 4),并且您尝试打印的当前工作目录名称中的字符不止于此. 这适用于大小为 3 或更小的目录。

而且,最后这里的许多其他人已经向您解释了如何解决它。

于 2011-05-23T16:19:38.583 回答
0

您无法找出指针所指向的内存块的大小sizeof。它将评估指针本身的大小。

将您的功能更改为:

void getCurrentDirectory(char *directory, size_t buf_max)
{
    getcwd(directory, buf_max);
}
于 2011-05-23T15:57:15.257 回答