const char* getOutPath()
{
return classVarStr.c_str();
}
我有上一个功能,
收到返回值
时有些奇怪我得到完整路径,但不包括第一个字符!
所以,如果路径是results/appName_subStr.dat
,我会得到esults/appName_subStr.dat
!
我将函数调用更改为
string getOutPath()
{
return classVarStr;
}
然后我在收到值后调用c_str()
以使第一个char
我猜它可能会发生因为函数堆栈pop可能以某种方式修改了地址?
任何人都面临类似的问题,原因可能是什么?
修改
class X
{
private:
string classVarStr;
public:
X(string in) : classVarStr(in)
const char* getOutPath()
{
return classVarStr.c_str();
}
string getOutPathStr()
{
return classVarStr;
}
}
class B
{
private:
X xinstance;
public:
B(int argc, char * argv[])
{
getSomepathFn(argc, argv);
}
string getAppPath1()
{
return xinstance.getOutPath(); // this create a string then pass a copy, and internally deleted
}
const char * getAppPath2()
{
return xinstance.getOutPathStr().c_str();// this is a problem, create a string, then pass const to the data, and deleted before the function call return, **Undefined behaviour** because the `getOutPathStr()` doesnt return a const reference
}
}
class appObj
{
void printMessage()
{
B obj = getBObj();
FILE *fileptr = fopen(obj->getAppPath2(), "a");// this is the faulty area
}
};
答案 0 :(得分:3)
如果您的函数使用具有自动存储持续时间的std::string
,则返回指向其内部存储的指针将产生 未定义的行为 ,因为该对象会自动被破坏一次执行超出范围(实际字符所在的内存也被释放):
const char* getOutPath()
{
std::string classVarStr;
...
return classVarStr.c_str();
}
这就是为什么返回本地std::string
对象副本的相同代码(按值)按预期工作的原因。
此代码(来自您的编辑):
const char * getAppPath2()
{
return xinstance.getOutPathStr().c_str();
}
调用getOutPathStr()
按值返回std::string
对象,这意味着在getAppPath2()
方法中,有一个此std::string
对象的副本。但是这个副本也只存在于这个范围内,它相当于:
const char * getAppPath2()
{
std::string copy = xinstance.getOutPathStr();
return copy.c_str();
}
这正是我在开头描述的情况〜> UB的原因。
答案 1 :(得分:1)
c_str()
返回的char指针仅在classVarStr
存在或未更改时有效。请参阅here如果您在该调用之后执行了任何更改字符串的操作,则char数组将更改。
第二个版本复制字符串,因此更安全。