【问题标题】:Passing const char* from std::string onto Lua stack turns into null将 const char* 从 std::string 传递到 Lua 堆栈变成 null
【发布时间】:2012-01-02 17:25:18
【问题描述】:

我有这段代码,我从我的游戏支持的不同类型的设备中收集设备 id,并将 lua 全局设置为当前设备的 id 值。 当我获得 iOS 设备的 id 时,我从混合的 C++/Objective-C 类接收到一个 const char* 并将其传递给 Lua 堆栈。一切正常。 但是,我从一段负责获取 Android 设备 ID 的代码中收到 std::string。当我推送 deviceId.c_str() 时,我在 Lua 中得到了 nil。 我已经尝试从负责获取设备 ID 的代码中传递 const char* ,但是当指针从函数返回时似乎出现了问题[这就是我决定返回字符串的原因,它可以正常工作]。

我应该怎么做才能让 const char* 从 std::string 中顺利传递出去?

编辑: 我试过使用 strcpy 但它不起作用:/ 仍然有同样的问题。

所以.. 负责从不同设备收集 deviceId 的代码如下所示:

#include "DeviceInfo.h"
#include "DeviceInfoIOS.h"
#include "DeviceInfoAndroid.h"
#include <string>


USING_NS_CC;

extern "C" {

const char *getDeviceId() {

    const char *deviceId;

    CCLog("test");

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    DeviceInfoIOS ios;
    deviceId = ios.getIOSDeviceId();
    CCLog("iOS platform %s", deviceId);

#endif  // CC_PLATFORM_IOS

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

    CCLog("Android platform");
    std::string tempId = getAndroidDeviceId();
    CCLog("Android platform test %s", tempId.c_str());
    char y[tempId.size() + 1];
    strcpy(y, tempId.c_str());
    deviceId = (const char*) y;
    CCLog("Android platform %s", deviceId);


#endif  // CC_PLATFORM_ANDROID
    CCLog("Finished platform check");
    return deviceId;
}

}

只是一个小提示:所有日志看起来都不错。 Devie id 可以正常传递。

这就是我将设备 ID 传递给 Lua 的方式:

//deviceInfo
CCLog("DeviceInfo load");
const char *deviceId = getDeviceId();
CCLog("DeviceInfo %s", deviceId);
lua_pushstring(d_state, deviceId);
lua_setglobal(d_state, "DEVICE_ID");

同样在这里,日志文件包含设备 ID。

【问题讨论】:

  • 可能是这样。这是一个混合环境,部分代码在 extern "C" 中。如何复制内存中的值以确保指针指向正确的位置。我不需要字符串容器,只需要字符。
  • 如果您想确保不泄漏,您可能确实需要一个字符串容器。但是如果你确定然后做一个strcpy()。 strcpy(data.c_str()) 该字符串将一直存在,直到您将其删除。
  • 这个是在什么编译器下编译的? C++ 不允许char y[tempId.size() + 1],这是一个动态大小的本地数组。 C 不允许std::string。那么是什么编译器和编译器设置导致这种 C99 和 C++ 的混搭起作用?
  • 嗯,说到 iOS 嗯,我不确定。无论 xcode 和 iOS SDK 4.x 附带什么。对于 Android,我使用的是 Android NDK r7。老实说,我不知道内部使用了哪些编译器。

标签: c++ lua stdstring


【解决方案1】:

您的getDeviceId 功能已损坏。 tempIdy 都是堆栈变量。一旦您返回,它们将被销毁。返回指向堆栈变量的指针总是一个坏主意。

你的函数应该返回一个std::string。否则,它应该返回一个char* 数组,它分配new,并且用户应该使用delete 解除分配。这就是为什么最好只返回std::string 的原因。或者,您可以使用固定大小(而不是基于字符串的大小)将 y 删除为 static 局部变量。

【讨论】:

  • hmmm 怎么在 iOS 上运行正常呢?另外..在做 lua_pushstring 值时应该被复制。我不明白这部分。如果我使用 new 和 delete,我会在调用 lua_setglobal.. 之后释放它,就像现在做的一样。
  • @Krystian:访问返回的指向堆栈变量的指针是未定义的行为。这意味着它在某些情况下看起来“工作正常”,但在其他情况下则不然。
  • @Krystian:查看this answer了解更多详情。
  • 嗯我知道这看起来像是我在滥用指针,但是这两种行为 [iOS 工作和 Android 不工作] 始终是 100% 可重现的。另一方面,这可能是由于 iOS 使用 Objective-C 并返回 [NSString UTF8String]。与 C/C++ 混合使用时,自动释放可能会以这种方式工作。我现在将尝试更改代码,看看会发生什么。
  • @Krystian:是否可重现并不重要; C 和 C++ 的规则说它是非法。我不知道 ObjectiveC 对此怎么说,因为它是垃圾收集等等。但就 C 和 C++ 而言,这是错误的。仅仅因为代码执行并执行您期望的操作并不能使其正确
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-27
相关资源
最近更新 更多