使用 std::string.c_str() 作为另一个方法的参数时的段错误

Posted

技术标签:

【中文标题】使用 std::string.c_str() 作为另一个方法的参数时的段错误【英文标题】:Segfault when using std::string.c_str() as an argument for another method 【发布时间】:2013-11-20 18:06:58 【问题描述】:

谁能告诉我为什么使用 c_str() 返回的 const char* 作为 stat(const char*, stat*) 中的参数会导致程序出现段错误?我想我已经将我的段错误缩小到由那条线引起的,但我不确定用什么来代替。我尝试使用 strcpy() 将字符串复制到字符数组中,但这只是导致程序在方法返回时出现段错误,这并没有好多少。

DIR * dir_p;
struct dirent *dir_entry_p;
list<string> files;
dir_p = opendir(".");
//push all file names to a list
while((dir_entry_p = readdir(dir_p))!=NULL)
    string name = dir_entry_p->d_name;
    files.push_front(name);

closedir(dir_p);
files.sort();
//count total blocks
//iterate through list
map<string,struct  stat*> fileStats;
struct stat * entry;
for(list<string>::iterator it = files.begin(); it != files.end(); it++)
    stat(it->c_str(),entry);
    fileStats[*it]=entry;
    cout<<entry->st_blocks<<" "<<*it<<endl;

【问题讨论】:

使用所有警告和调试信息进行编译(例如使用g++ -Wall -g)。改进代码直到没有给出警告。使用valgrind 和您的调试器(例如gdb @H2CO3,我愿意接受有关如何避免“未格式化、无法阅读的混乱”的建议。简单地说它是这样的,这不是我以后编写代码时可以考虑的事情。事实上,您的评论毫无帮助且具有煽动性。 【参考方案1】:

我不认为这是 c_str() 在这里制造麻烦,而是您如何使用 struct stat。 你应该创建一个struct stat 实例并传递它的地址:

// ...

//iterate through list
map<string,struct  stat> fileStats;
for(list<string>::iterator it = files.begin(); it != files.end(); it++)
    struct stat entry;
    stat(it->c_str(),&entry);
    fileStats[*it]=entry;
    cout<<entry.st_blocks<<" "<<*it<<endl;

您正在做的是让stat() 写入来自未初始化指针的地址(这很可能会导致段错误)。

请注意,您还需要更改地图类型才能使其正常工作。

【讨论】:

@Dazedy 注意如何初始化指针(内存泄漏等)。我发布的代码应该可以正常工作,并且不会增加任何额外的开销。

以上是关于使用 std::string.c_str() 作为另一个方法的参数时的段错误的主要内容,如果未能解决你的问题,请参考以下文章

std::string::c_str() 覆盖函数返回的前一个

C++string类型与C语言字符数组的转换 std::string.c_str()函数

std::string::c_str() 结果的生命周期是多少?

std::string::c_str() 结果的生命周期是多少?

为啥我仍然可以在字符串范围之外访问 std::string::c_str() 返回的 char 指针? [复制]

C++ 中的 StringStream/c_str() 损坏