【问题标题】:Empty string when trying to convert const char * to NSString尝试将 const char * 转换为 NSString 时出现空字符串
【发布时间】:2013-03-24 12:22:55
【问题描述】:

我在尝试从 const char * 获取 NSString 时遇到了一个奇怪的错误。

// in my obj c class
void myObjCMethod {
    const char* charString = myCFunctionReturningConstCharPtr(); 
    printf("%s \n", charString); // prints the correct string

    // ...put a brakpoint here... 

    NSString * nsString1 = [NSString stringWithUTF8String:charString];
    NSLog(@"%@", nsString1); // prints nothing

    NSString * nsString2 = [NSString stringWithFormat:@"%s",charString];
    NSLog(@"%@", nsString2); // prints nothing either
}

来自我的 c 方法的 const char 可以很好地打印到控制台。但是尝试转换为 NSString 会导致空字符串。 现在最奇怪的是,当我尝试调试代码并设置断点(如上所示)时,我的 NSString 突然变为有效!

那又如何——我的测量改变了结果?很久以前的物理课听起来很熟悉,但我怀疑这里涉及到量子力学。

注意:

我暂时省略了myCFunctionReturningConstCharPtr() 的实现,因为它会增加另一层可能与当前问题无关的复杂性(涉及多个 c++ 库,字符串已从 char 指针转换为 std ::字符串并返回)。

这两天我一直在努力解决这个问题,非常感谢任何帮助!谢谢

编辑:

字符串最初来自 PowerVR 的 Insider SDK 中的结构 SPODNode。 我们有:

struct SPODNode {
    PVRTchar8 *pszName;
    // ...
}

与:

typedef char PVRTchar8;

在我的代码中:

std::string MyCppClass::pvrNodeName() {
    if (node && node->pszName) {
        string stdName(node->pszName);
        return stdName;
    }
    return string();
}

最后在myCFunctionReturningConstCharPtr():

const char * myCFunctionReturningConstCharPtr() {
    std::string stdString = myCppClassInstace->pvrNodeName()
    return stdString.c_str();
}

希望对你有帮助!

【问题讨论】:

  • 我怀疑myCFunctionReturningConstCharPtr()。可以展示一下吗?
  • 不是那么容易,涉及的代码太多。我将尝试将其分解并将其添加到我的问题中。我希望给定的例子能代表它本身。
  • 我对您的const char* 的返回方式很感兴趣。尤其是通过调用data()c_str()从本地std::string对象获取。
  • 你至少能显示“正确字符串”的输出吗?是否涉及任何非 ASCII 字符?如果字符串不是正确的 UTF-8,stringWithUTF8String 将失败。
  • 字符串“foo”也会出现问题

标签: c++ objective-c


【解决方案1】:

const char * 是通过在 std::string 上调用 .c_str() 获得的。

很可能您的程序有未定义的行为,因为您正在返回一个指向字符数组的指针,该字符数组在从函数myCFunctionReturningConstCharPtr() 返回时被释放。

其实你返回的那个const char*指向一个字符数组,这个数组是由一个本地的std::string对象封装的; std::string 对象的析构函数会释放该数组,并在本地对象超出范围时调用析构函数,即从函数返回时。

稍后尝试取消引用您收到的指针会导致未定义行为,这意味着任何事情都可能发生。这包括您的程序在被调试时似乎运行良好,但在没有附加调试器的情况下运行时却没有。

您应该让您的函数返回(按值)std::string,然后如果您需要获取封装的 C 字符串,则在该返回值上调用 c_str()

std::string charString = myCFunctionReturningConstCharPtr(); 
printf("%s \n", charString.c_str()); // prints the correct string

【讨论】:

  • 请查看我上面更新问题中的代码。据我了解,这就是我所做的。我正在使用 c_str() 转换我的标准字符串。结果是一个常量,因此当我返回它时应该仍然有效。还是我错过了什么?
  • @de.:不,它无效。正如我在回答中所写,该字符数组归本地 std::string 对象所有,当它超出范围时,字符数组将被删除。按照我的建议,返回 std::string 而不是 const char*
  • 好的,我明白了。但我必须转换为 c,因为我的 API 只有 c,没有 c++。
  • @de。在这种情况下,您可以分配一个新的字符数组并将c_str() 返回的字符数组复制到其中。在这种情况下,客户端将有责任对其进行delete[]。或者,您可以让客户端将缓冲区传递给您的函数,因此函数本身只需将c_str() 的结果复制到其中而不分配它。这个解决方案是更好的 IMO,因为客户端可以选择如何分配缓冲区(无论是在堆栈上还是在堆上)
  • 谢谢安迪,我会遵循你的第二个建议。这有望解决我的问题。一旦我运行它,我会回来的。
猜你喜欢
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多