C++ 如何从C';s";getcwd";功能
很抱歉一直在讨论这个问题,但我正在努力学习:)。这有什么好处吗?是的,我关心内存泄漏。我找不到一个合适的方法来预分配char*,因为似乎没有跨平台的方法C++ 如何从C';s";getcwd";功能,c++,memory-leaks,cross-platform,getcwd,C++,Memory Leaks,Cross Platform,Getcwd,很抱歉一直在讨论这个问题,但我正在努力学习:)。这有什么好处吗?是的,我关心内存泄漏。我找不到一个合适的方法来预分配char*,因为似乎没有跨平台的方法 const string getcwd() { char* a_cwd = getcwd(NULL,0); string s_cwd(a_cwd); free(a_cwd); return s_cwd; } 更新2:如果没有Boost或Qt,最常见的东西可能会变得冗长(请参阅公认的答案)您需要检查cwd是否为N
const string getcwd()
{
char* a_cwd = getcwd(NULL,0);
string s_cwd(a_cwd);
free(a_cwd);
return s_cwd;
}
更新2:如果没有Boost或Qt,最常见的东西可能会变得冗长(请参阅公认的答案)您需要检查cwd是否为NULL。然后它将在Mac、Windows和Linux上工作。但是,它不符合POSIX
编辑:perror不退出程序,因此您应该退出、抛出异常或执行某些操作。这将在Windows和Linux上运行,因为它们都支持
getcwd
的buf
参数为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;
}
const字符串getcwd()
{
大小为1024;
char*buf=NULL;
char*r_buf;
做{
buf=静态铸件(realloc(buf,buf尺寸));
r_buf=getcwd(buf,buf_大小);
如果(!r_buf){
if(errno==ERANGE){
buf_尺寸*=2;
}否则{
免费(buf);
抛出std::runtime_error();
//或者其他一些错误处理代码
}
}
}而(!r_buf);
字符串str(buf);
免费(buf);
返回str;
}
上面的代码以1024缓冲区大小开始,然后,如果getcwd
抱怨缓冲区太小,它会将大小加倍并重试,然后重复,直到有足够大的缓冲区并成功
注意,第一个参数为NULL的调用
realloc
与malloc
相同,如果您想保持标准,getcwd
不需要做任何事情,只要您向它传递NULL;相反,您应该在堆栈上分配一个缓冲区,该缓冲区对于大多数情况(比如255个字符)来说“足够大”,但要为getcwd
可能会因errno==ERANGE而失败的情况做好准备;在这种情况下,您应该分配一个更大的缓冲区,并在必要时增加其大小
类似的东西可能会起作用(注意:没有经过测试,只是从头开始编写,当然可以改进):
string getcwd()
{
常量大小\u t chunkSize=255;
const int maxChunks=10240;//当前路径的2550 kib就足够了
char stackBuffer[chunkSize];//正常情况下的堆栈缓冲区
if(getcwd(stackBuffer,sizeof(stackBuffer))!=NULL)
返回堆栈缓冲区;
if(errno!=ERANGE)
{
//这不是语言,所以我们不知道如何处理
抛出std::runtime_错误(“无法确定当前路径”);
//当然,您可以选择不同的错误报告方法
}
//好的,堆栈缓冲区不够长;回退到堆分配
对于(int chunks=2;chunks您不能将空指针传递给std::string
的构造函数,因此必须检查getcwd()
返回的缓冲区指针是否为空。此外,传递给getcwd()
的缓冲区指针
你应该使用ISO C++兼容版本<代码> .GETCWD < /Cord>我认为,返回<代码> const字符串没有意义,并且应该使用<代码>免费< /C> >(至少根据MSDN):
当然,您还应该检查\u getcwd()
是否返回空值。这怎么样?它很短,异常安全,并且不会泄漏
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());
}
\include//定义文件名\u MAX
#包含//用于getcwd()
std::字符串GetCurrentWorkingDir()
{
std::字符串cwd(“\0”,文件名\u MAX+1);
返回getcwd(&cwd[0],cwd.capacity());
}
查看rubenvb的相关内容。什么是CAKE_getcwd
?Google什么也找不到。普通的getcwd
在Solaris上无法像您所希望的那样工作。尽管当您向它传递空指针时它会分配内存,但它分配的内存量完全基于第二个getcwd
参数,而不是它所使用的字符串长度想要返回。因此,在您的示例中,它将分配零字节(或者简单地使用EINVAL失败)。CAKE_getcwd是我为Windows上的纯getcwd vs_getcwd的弃用警告定义的变通方法。Fixed我个人更喜欢信息丰富的标题,而不仅仅是“主题问题”…我们知道这是一个问题,因为标签,我们知道它是什么主题,所以细节很好:)固定的标题和Wrand将试图在未来的GETCWWD中更具描述性。但是,如果你看前面的问题,Ruube用IFDEF来覆盖这个问题。@马修:对不起,我的意思是说ISO C++的一致性。得到了,从MSDN复制粘贴:我认为POSIX标准在这里是愚蠢的,因为没有安全的方法。ely分配一个保证足够大的字符*>:s@ruben,我不同意。_PC_PATH_MAX是推荐的方法。值得注意的是,getcwd永远不会出现缓冲区溢出,因为您会传递它的大小。如果缓冲区太小,它最多会给您一个错误。MSDN在POSIX上不是一个可靠的来源。从未说过任何关于t的事情他需要成为POSIX。我在这里放弃了POSIX的完全兼容性,并且很高兴:)@ruben,你说“POSIX标准在这里很愚蠢”。我指出的是,如果它只需要在POSIX上工作,那么有一个推荐的解决方案。自然地,跨平台工作会增加复杂性。我理解,并且对我的顽固决定感到遗憾“没有增压或Qt"为了让我的程序小巧美观。谢谢。如果你想让它符合POSIX标准并处理任意路径长度,这就是你必须要做的。如果你想让它更短,你必须放弃这两个要求中的一个。好吧,这就是我把POSIX抛到一边的地方:)你可以自由地这样做,但因为重点是你的问题似乎有点矛盾
string getcwd()
{
char* a_cwd = _getcwd(NULL, 0);
string s_cwd(a_cwd);
free(a_cwd);
return s_cwd;
}
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());
}