2012-06-13 209 views
2

使用字符串指針我有一個示例項目here on github,我創建了一個C++包裝類,我想在Objective-C使用一個外部的C++庫。在C++和Objective-C

我不明白爲什麼我返回的指針有時是正確的,有時是錯誤的。這裏是示例輸出:

Test Data = 43343008 
In Compress 43343008 
Returned Value = 43343008 
Casted Value = 43343008 

Test Data = 2239023 
In Compress 2239023 
Returned Value = 2239023 
Casted Value = 2239023 

Test Data = 29459973 
In Compress 29459973 
Returned Value = 29459973 
Casted Value = l.remote 

Test Data = 64019670 
In Compress 64019670 
Returned Value = 
Casted Value = stem.syslog.master 

在上面的輸出中,您可以看到按鈕的第一次和第二次點擊輸出我期待的結果。在其他每次點擊中,返回值或鑄造值都是無效的。我假設這是因爲我的指針指向了一個我並不期待的地址。當多次運行該應用程序時,任何按鈕點擊都可能是正確的或錯誤的。

我也試過用單線程,但經歷了類似的結果。

完整的代碼是github但這裏有重要的位。

ViewController.m

#import "ViewController.h" 

extern const char * CompressCodeData(const char * strToCompress); 

@implementation ViewController 

... 

// IBAction on the button 
- (IBAction)testNow:(id)sender 
{ 
    [self performSelectorInBackground:@selector(analyze) withObject:nil]; 
} 

- (void)analyze 
{ 
    @synchronized(self) { 

     const char *testData = [[NSString stringWithFormat:@"%d", 
         (int)(arc4random() % 100000000)] UTF8String]; 
     NSLog(@"Test Data = %s", testData); 

     const char *compressed = CompressCodeData(testData); 
     NSLog(@"Returned Value = %s", compressed); 

     NSString *casted = [NSString stringWithCString:compressed 
              encoding:NSASCIIStringEncoding]; 
     NSLog(@"Casted Value = %@\n\n", casted); 

    } 
} 

@end 

SampleWrapper.cpp

#include <iostream> 
#include <string.h> 
#include <CoreFoundation/CoreFoundation.h> 

using namespace std; 

extern "C" 
{ 
    extern void NSLog(CFStringRef format, ...); 

    /** 
    * This function simply wraps a library function so that 
    * it can be used in objective-c. 
    */ 
    const char * CompressCodeData(const char * strToCompress) 
    { 
     const string s(strToCompress); 

     // Omitted call to static method in c++ library 
     // to simplify this test case. 

     //const char *result = SomeStaticLibraryFunction(s); 
     const char *result = s.c_str(); 

     NSLog(CFSTR("In Compress %s"), result); 
     return result; 
    } 

} 

回答

4

您在返回對象的指針已被釋放。

const string s(strToCompress); 
… 
const char *result = s.c_str(); 

NSLog(CFSTR("In Compress %s"), result); 
return result; 

s不存在後CompressCodeData()功能是結束了,所以指針,它的內存是無效的。


你可以分配一塊內存來保存響應,但是由調用者來釋放它。

char *compressed = CompressCodeData(testData); 
NSLog(@"Returned Value = %s", compressed); 

NSString *casted = [NSString stringWithCString:compressed 
             encoding:NSASCIIStringEncoding]; 
free(compressed); 
NSLog(@"Casted Value = %@\n\n", casted); 

… 

const char * CompressCodeData(const char * strToCompress) 
… 
char *result = strdup(s.c_str()); 

另一種解決方案是傳入內存來存儲數據。

char compressed[2048]; // Or whatever! 
CompressCodeData(testData, compressed, sizeof(compressed)); 
NSLog(@"Returned Value = %s", compressed); 

NSString *casted = [NSString stringWithCString:compressed 
             encoding:NSASCIIStringEncoding]; 
NSLog(@"Casted Value = %@\n\n", casted); 

… 

void CompressCodeData(const char * strToCompress, char *result, size_t size) 
… 
s.copy(result, size - 1); 
result[s.length() < size ? s.length() : size-1] = '\0'; 
+0

謝謝你,這回答完美。 – JamesOR