c_str回来了,但缺少第一个字符

c_str returned but missing first char

本文关键字:第一个 字符 str 回来了      更新时间:2023-10-16
const char* getOutPath() 
{
  return classVarStr.c_str();
}

我有前面的功能,

当我收到返回值时有些奇怪,

我得到了完整的路径,但不包括第一个字符!

所以如果路径results/appName_subStr.dat我就会esults/appName_subStr.dat

我将函数调用更改为

string getOutPath() 
{
  return classVarStr;
}

然后我在收到值后调用c_str()以获得第一个char的正确路径

我猜这可能是因为函数堆栈弹出可能以某种方式修改了地址而发生的?

任何人都面临类似的问题,原因可能是什么?

编辑:

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
     }
};

如果您的函数使用具有自动存储持续时间的std::string,则返回指向其内部存储的指针将产生未定义的行为,因为一旦执行超出范围,对象就会自动销毁(实际字符所在的内存也被释放):

const char* getOutPath() 
{
    std::string classVarStr;
    ...
    return classVarStr.c_str();
}

这就是为什么返回本地std::string对象副本(按值)的相同代码按预期工作的原因。


此代码(来自您的编辑):

const char * getAppPath2() 
{
    return xinstance.getOutPathStr().c_str();
}

调用按值返回对象std::string getOutPathStr(),这意味着在 getAppPath2() 方法中,有一个此std::string对象的副本。但是这个副本也只存在于这个范围内,它相当于:

const char * getAppPath2() 
{
    std::string copy = xinstance.getOutPathStr();
    return copy.c_str();
}

这正是我在开头描述的情况~>UB的原因。

c_str() 返回的 char 指针仅在classVarStr存在或未更改时才有效。看这里 如果您在该调用后执行了更改字符串的任何操作,则 char 数组将更改。
第二个版本复制字符串,因此更安全。