NSString UTF8String访问不好

时间:2013-06-24 13:02:51

标签: c++ ios objective-c nsstring

我需要将NSString转换为std :: string,并使用[str UTF8String]成功完成。但出于某种原因,当我在我的一个NSStrings上尝试它时,我得到EXC_BAD_ACCESS错误。

我正在检查str是否为空,所以我不确定为什么会发生这种情况。我还尝试确保str确实是一个NSString,但以下内容会引发同样的错误:

const char* className = class_getName([str class]);

我错过了什么?

编辑:我正在使用的代码:

NSMutableArray* m_imageInfos; // defined in ClassName.h
RUBEImageInfo *touchedImgInfo; // also defined in ClassName.h

这是一个cocos2d项目,根据游戏流程我将其他类型为RUBEImageInfo的对象加载到m_imageInfos中。相关代码:

RUBEImageInfo* imgInfo = [[RUBEImageInfo alloc] init];
imgInfo->sprite = sprite;
imgInfo->name = [NSString stringWithUTF8String:newImg->name.c_str()];
std::cout << "loadBody imgInfo name " << [imgInfo->name UTF8String] << "\n";

std :: cout正确打印出图像名称。我应该补充说,名称是字符串和int的串联,如下所示:

std::stringstream sstm;
sstm << img->name << counter;
newImg->name = sstm.str();

在ClassName.mm中,CCTouchesBegun我检查了哪个b2Body被触摸,然后循环遍历m_imageInfos以查看触摸了哪个imageInfo:

for(int j=0; j<[m_imageInfos count]; j++) {
    RUBEImageInfo *rif = m_imageInfos[j];
    if(rif->body == body) {
        touchedImgInfo = rif;
        printf("ccTouchesBegun touchedImgInfo %p \n", touchedImgInfo);
        printf("ccTouchesBegun touchedImgInfo name %p \n", [touchedImgInfo->name UTF8String]);
            break;
     }
 }

第一个打印输出通过并给出如下结果:

ccTouchesBegun touchedImgInfo 0x98b84f0

但第二次打印输出错误EXE_BAD_ACCESS。为了增加复杂性,这种情况大多数时间都会发生。每10-15次尝试一次,它运行正常。

为了完整代码,这是RUBEImageInfo.h:

#import "cocos2d.h"

@interface RUBEImageInfo : NSObject {

   @public CCSprite* sprite;               
   @public NSString* name;                 
   @public class b2Body* body;             
   @public float scale;                    
   @public float angle;                    
   @public CGPoint center;                 
   @public float opacity;                  
   @public bool flip;                      
   @public int colorTint[4];               
}

@end

1 个答案:

答案 0 :(得分:1)

imgInfo->name = [NSString stringWithUTF8String:newImg->name.c_str()];

这是错误的内存管理。您直接将不拥有的对象分配给另一个对象的实例变量。如果您在相同的方法中使用它,它将起作用,但是在当前自动释放池的生命周期内不保证该对象的寿命。所以最终,实例变量指向垃圾。

理想情况下,您应该使用访问器而不是直接分配实例变量。这是Cocoa应用程序中惯用的方法。如果由于某种原因你根本无法使用访问器,那么你需要确保在使用实例变量的任何地方正确管理你的内存。