我正在尝试使用函数将C字符串转换为std :: string。该函数在64位gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)
上正常工作。但是当我使用-O2
或-O3
优化进行编译时,会出现段错误。它适用于-O1
。有人可以建议修复或解决这个问题吗?功能如下:
void make_name(unsigned const &i, string &h_file)
{
char h_str[10];
sprintf(h_str, "tmp/%09d.hb", i);
h_file = string(h_str);
}
答案 0 :(得分:9)
简单:提供足够的缓冲区。或者使用std::stringstream
。
答案 1 :(得分:5)
char h_str[10];
sprintf(h_str, "tmp/%09d.hb", i);
这是未定义的行为。您正在尝试将大约17个字节的数据写入10字节数组:
tmp/
是四。%09d
将扩展至至少九个。.hd
是三。\0
是一个。不要那样做。未定义的行为意味着功能的所有保证都是无效的。
事实上,如果你想成为一个真正体面的C ++开发人员,你应该尽可能地避免遗留的东西。
在学习和需要在C和C ++中运行的库代码时,这很好。但是,对于C ++代码,使用该语言的非遗留部分要强得多。
以下程序显示如何执行此操作如果不必恢复cstdio/stdio.h
中的旧版C内容:
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
void make_name (unsigned int i, string &h_file) {
stringstream ss;
ss << "tmp/" << setw(9) << setfill('0') << i << ".hb";
h_file = ss.str();
}
int main() {
string s;
make_name (42u, s);
cout << s << '\n';
return 0;
}
顺便说一句,您会看到我已经更改了方法签名以按值传递
i
。那是因为我不确定将它作为const
引用有什么好处。如果您 找到优势,请随时更改回来。
答案 2 :(得分:1)
最好是永远不要使用C字符串。
std::string make_name(unsigned i)
{
std::ostringstream str;
str << "tmp/" << std::setfill('0') << std::setw(9) << i << ".hb";
return std::move(str.str());
}