很抱歉一直在强调这一点,但我正在努力学习:)。这有什么好处吗?是的,我关心内存泄漏。我找不到一种像样的方式来预分配 char*,因为似乎根本就没有跨平台的方式。
const string getcwd()
{
char* a_cwd = getcwd(NULL,0);
string s_cwd(a_cwd);
free(a_cwd);
return s_cwd;
}
UPDATE2:没有 Boost 或 Qt,最常见的东西可能会变得冗长(见接受的答案)
很抱歉一直在强调这一点,但我正在努力学习:)。这有什么好处吗?是的,我关心内存泄漏。我找不到一种像样的方式来预分配 char*,因为似乎根本就没有跨平台的方式。
const string getcwd()
{
char* a_cwd = getcwd(NULL,0);
string s_cwd(a_cwd);
free(a_cwd);
return s_cwd;
}
UPDATE2:没有 Boost 或 Qt,最常见的东西可能会变得冗长(见接受的答案)
如果你想保持标准,getcwd
如果你传递一个 NULL 就不需要做任何事情;相反,您应该在堆栈上分配一个对于大多数情况(例如 255 个字符)“足够大”的缓冲区,但要为getcwd
可能失败的情况做好准备errno==ERANGE
;在这种情况下,您应该分配一个更大的缓冲区,并在必要时增加其大小。
像这样的东西可以工作(注意:未经测试,只是从头开始编写,肯定可以改进):
string getcwd()
{
const size_t chunkSize=255;
const int maxChunks=10240; // 2550 KiBs of current path are more than enough
char stackBuffer[chunkSize]; // Stack buffer for the "normal" case
if(getcwd(stackBuffer,sizeof(stackBuffer))!=NULL)
return stackBuffer;
if(errno!=ERANGE)
{
// It's not ERANGE, so we don't know how to handle it
throw std::runtime_error("Cannot determine the current path.");
// Of course you may choose a different error reporting method
}
// Ok, the stack buffer isn't long enough; fallback to heap allocation
for(int chunks=2; chunks<maxChunks ; chunks++)
{
// With boost use scoped_ptr; in C++0x, use unique_ptr
// If you want to be less C++ but more efficient you may want to use realloc
std::auto_ptr<char> cwd(new char[chunkSize*chunks]);
if(getcwd(cwd.get(),chunkSize*chunks)!=NULL)
return cwd.get();
if(errno!=ERANGE)
{
// It's not ERANGE, so we don't know how to handle it
throw std::runtime_error("Cannot determine the current path.");
// Of course you may choose a different error reporting method
}
}
throw std::runtime_error("Cannot determine the current path; the path is apparently unreasonably long");
}
顺便说一句,在你的代码中有一个非常错误的事情:你试图用delete
:你绝对不应该这样做,请记住,每种分配方法都有其释放对应物,并且它们不能不匹配。
buf
这将适用于 Windows 和 Linux,因为当参数getcwd
为 NULL时,它们都支持自动分配行为。但是,请注意,这种行为不是标准的,因此您可能会在更深奥的平台上遇到问题。
但是,您可以在不依赖此行为的情况下执行此操作:
const string getcwd()
{
size_t buf_size = 1024;
char* buf = NULL;
char* r_buf;
do {
buf = static_cast<char*>(realloc(buf, buf_size));
r_buf = getcwd(buf, buf_size);
if (!r_buf) {
if (errno == ERANGE) {
buf_size *= 2;
} else {
free(buf);
throw std::runtime_error();
// Or some other error handling code
}
}
} while (!r_buf);
string str(buf);
free(buf);
return str;
}
上面的代码以 1024 的缓冲区大小开始,然后,如果getcwd
抱怨缓冲区太小,它会加倍大小并再次尝试,并重复直到它有足够大的缓冲区并成功。
请注意,realloc
第一个参数为 NULL 的调用与malloc
.
您不能将空指针传递给 a 的构造函数std::string
,因此您必须检查getcwd()
返回的缓冲区指针是否为空。此外,您传递给的缓冲区指针getcwd()
不得为 null。
std::string getcwd() {
char buf[FILENAME_MAX];
char* succ = getcwd(buf, FILENAME_MAX);
if( succ ) return std::string(succ);
return ""; // raise a flag, throw an exception, ...
}
我认为您应该使用符合 ISO C++ 标准的版本_getcwd
。返回 a 是没有意义的const string
,您应该使用它free
来解除分配(至少根据 MSDN):
string getcwd()
{
char* a_cwd = _getcwd(NULL, 0);
string s_cwd(a_cwd);
free(a_cwd);
return s_cwd;
}
当然,您还应该检查是否_getcwd()
返回 NULL。
您需要检查 a_cwd 是否为 NULL。然后它将在 Mac、Windows、Linux 上运行。但是,它不符合 POSIX 标准。
编辑: perror 不会退出程序,所以你应该退出,抛出异常,或者做一些事情。
这个怎么样?它很短,异常安全,并且不会泄漏。
std::string getcwd() {
std::string result(1024,'\0');
while( getcwd(&result[0], result.size()) == 0) {
if( errno != ERANGE ) {
throw std::runtime_error(strerror(errno));
}
result.resize(result.size()*2);
}
result.resize(result.find('\0'));
return result;
}
当“字符串构造函数”为您做所有事情时:
#include <stdio.h> // defines FILENAME_MAX
#include <unistd.h> // for getcwd()
std::string GetCurrentWorkingDir()
{
std::string cwd("\0",FILENAME_MAX+1);
return getcwd(&cwd[0],cwd.capacity());
}