2009-12-29 47 views
0

我已經定義了一個結構,並且想將它的一個值賦給一個NSMutableDictionary。當我嘗試時,我得到一個EXC_BAD_ACCESS。下面是代碼:什麼是結構中的NSString?

//in .h file 
typedef struct { 
NSString *valueOne; 
NSString *valueTwo; 
} myStruct; 

myStruct aStruct; 

//in .m file 
- (void)viewDidLoad { 
[super viewDidLoad]; 
aStruct.valueOne = @"firstValue"; 
} 

//at some later time 
[myDictionary setValue:aStruct.valueOne forKey:@"key1"]; //dies here with EXC_BAD_ACCESS 

這是在調試器控制檯輸出:

(gdb) p aStruct.valueOne 
$1 = (NSString *) 0xf41850 

有沒有辦法告訴什麼aStruct.valueOne的價值是什麼?

既然是NSString,爲什麼字典有這樣的問題呢?

-------------編輯-------------

此編輯基於下面的一些評論。

該問題似乎出現在結構內存分配中。正如其中一條評論所述,我沒有將結構值賦給viewDidLoad中的字典的問題。問題是,後來我遇到了一個關於結構的問題。就在錯誤之前,我做的:

po aStruct.oneValue 

Program received signal EXC_BAD_ACCESS, Could not access memory. 
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000 
0x9895cedb in objc_msgSend() 
The program being debugged was signaled while in a function called from GDB. 
GDB has restored the context to what it was before the call. 
To change this behavior use "set unwindonsignal off" 
Evaluation of the expression containing the function (_NSPrintForDebugger) will be abandoned. 

這只是EXC_BAD_ACCESS之前發生:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
[formatter setDateFormat:@"MM-dd-yy_HH-mm-ss-A"]; 
NSString *date = [formatter stringFromDate:[NSDate date]]; 
[formatter release]; 

aStruct.valueOne =日期;

所以內存問題最有可能在我發佈格式化程序。日期var沒有保留。我應該做的

NSString *date = [[formatter stringFromDate:[NSDate date]] retain]; 

哪些工作,但然後我留下了內存泄漏。

+0

EXC_BAD_ACCESS與取消引用解除分配的對象(或未初始化的對象)有關。你確定你初始化了'myDictionary'還是沒有釋放'myStruct'? – notnoop 2009-12-29 06:28:15

+0

我已經更新了OP。請在「編輯」條目後查看 – 4thSpace 2009-12-29 07:53:46

+0

請注意,如果使用ARC Objective-C對象在結構或聯合中被禁止 – elitalon 2013-01-23 17:47:56

回答

1

我重新創建了你的代碼,並把NSDictionary的setValue方法放在aStruct.valueOne = @「firstValue」行的下面。它完美無缺地工作。所以,你的問題不在NSString中,但是其中一個對象(aStruct或myDictionary)會在某個地方被取消分配。你可以嘗試以下方法:

static myStruct aStruct; 

要打印aStruct.valueOne的值,你可以使用:

NSLog(@"aStruct.valueOne = %@ \n", aStruct.valueOne); 

此外,您還可以檢查myDictionary的保留計數,看它是否仍被分配。但是,試圖檢查已經釋放的對象的保留計數將導致錯誤。但它會在錯誤日誌中告訴你,該對象已被釋放。

NSLog(@"Retain Count of myDictionary = %i \n", myDictionary.retainCount); 

希望有幫助。

1

不知道它爲什麼會崩潰,但不是p,而是使用po,它將打印NSString的內容或任何NS/CF對象的描述。

1

嘗試啓用殭屍來檢查你在哪裏過度釋放對象。項目 - >編輯主動可執行文件 - >參數選項卡 - >添加變量NSZombieEnabled並賦值YES。 (並將複選框設置爲YES)。

然後,您應該在跟蹤中獲得有關您的錯誤的更多信息。

不要忘記關閉NSZombieEnabled複選框。

編輯:

當您將valueOne

aStruct.valueOne = @"firstValue"; 

實際上創建NSString對象,並把它放到自動釋放池。因此,稍後當您嘗試將該對象傳遞給您的字典時,它可能已被自動釋放,這就是爲什麼您要獲得EXC_BAD_ACCESS。當你爲結構指定新的指針時,你必須實現一些方法來爲你做內存管理。事情是這樣的:

- (void)setValueOne:(NSString *)newValueOne { 
    [aStruct.valueOne autorelease]; 
    aStruct.valueOne = [newValueOne retain]; 
} 

因此,在您viewDidLoad你必須使用你的新方法:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // make sure it is nil "on startup" because setValueOne: method will send autorelease method 
    aStruct.valueOne = nil; 
    aStruct.valueTwo = nil; 
    [self setValueOne:@"firstValue"]; 
} 
+0

謝謝。當我在調試窗口中打開結構時,我只能看到NSZombieEnabled信息。它沒有給出任何關於這種情況發生的跡象。你有什麼建議可以追蹤它嗎? – 4thSpace 2010-04-19 00:21:47

0

任何「類*實例」是指向的對象。您看到的$1 = (NSString *) 0xf41850實際上是指向當前分配用於存放valueOne的內存空間的指針。通常與EXEC BAD ACCESS相關的問題是,內存空間不是永久分配來保存valueOne,並且稍後會被回收,通常在該方法執行完成後立即執行(稱爲垃圾回收)。然後,當你以後嘗試訪問它時,例如從一個不同的方法或甚至相同的方法,但在後續的執行中,系統說'嘿,該內存地址用於其他事情',它會引發Exec Bad Access錯誤。

有沒有辦法告訴什麼aStruct.valueOne的價值 是什麼?

好,調試器,此刻的你樹立的價值,應該可以挑上的定義並向您顯示字面值;它應該知道0xf41850處的內存空間映射到NSString類,它是一些長度爲字節的數組,並且該地址處的字節以特定方式編碼,因此應該映射成可以在調試器中顯示的一些字符串。然而,後來呢,不,系統沒有(有效的)關於這個空間包含的想法,因爲它可以包含任何東西。因此,當您遇到EXEC BAD ACCESS時,這意味着您不會長時間保留該值,這可能是因爲您沒有故意保留它,或者已經釋放它(有意或無意讓系統釋放它)。