0

私はこの問題に直面しており、メモリ管理の基本的な概念がいくつか欠けていることを認めています。私はこれを解決できず、私を信頼することができませんでした。私は非常に多くのことを試してきました。

私のアプリには、RS232 ポートから読み取る 4 つのスレッド (将来的には最大 12 スレッドになる可能性があります) があります。各スレッド ( threadRS232Read) で、appendString を使用して RS232 文字をそれぞれの NSMutableString に追加します。NSMutableString は、完全なテストが完了するまで、appendString によって信じられないほど大きくなります。そして定期的にテスト内でclearRdBuffStr、文字列をクリアするために呼び出されます。app は常に appendString でクラッシュします。運が良ければ、いくつかのテストを実行できますが、通常、最初の実行でクラッシュします。以下は、コード スニペットとクラッシュ ログです。

AppController.h
...
`@interface AppController : NSObject {
...
NSMutableString *buffStr1, *buffStr2, *buffStr3, *buffStr4;
...}

AppController.m
...
//in -(id)init
buffStr1 = [[NSMutableString alloc] initWithString:@""];
buffStr2 = [[NSMutableString alloc] initWithString:@""];
buffStr3 = [[NSMutableString alloc] initWithString:@""];
buffStr4 = [[NSMutableString alloc] initWithString:@""];
...
// in -(void)dealloc
[buffStr1 release];
[buffStr2 release];
[buffStr3 release];
[buffStr4 release];`

別のファイル RS232RW.m では、スレッドを使用して buffStr1 を 4 に更新します。

RS232RW.m
- (void)threadRS232Read:(id)argument { 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
....
//read from RS232 port buffer and etc...
NSString *buffStr = [NSString stringWithUTF8String:buff];
    switch (portNo) {
        case 0:
            if (buffStr != nil)
            {
                [buffStr1 appendString:buffStr];
            }

            break;
        case 1:
            if (buffStr != nil)
            {
                [buffStr2 appendString:buffStr];
            }
            break;
        case 2:
            if (buffStr != nil)
            {
                [buffStr3 appendString:buffStr];
            }

            break;
        case 3:
            if (buffStr != nil)
            {
                [buffStr4 appendString:buffStr];
            }
            break;
        case 4:
            if (buffStr != nil)
            {
                [buffStr5 appendString:buffStr];
             }
            break;

        ....

// clearRdBuffStr will be called by the other part of the program to clear this buffer.
-(void) clearRdBuffStr:(int) portNo {
switch (portNo) {
    case 0:
        [buffStr1 setString:@""];
        break;
    case 1:
        [buffStr2 setString:@""];
        break;
    case 2:
        [buffStr3 setString:@""];
        break;
    case 3:
        [buffStr4 setString:@""];
        break;
    ....

アプリは常に上記の appendString の 1 でクラッシュします。

クラッシュログは次のとおりです。

   ....


Crashed Thread:  3

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information:
objc[584]: garbage collection is OFF
*** error for object 0x6d02b600: double free
....
Thread 3 Crashed:
0   libsystem_kernel.dylib          0x905819c6 __pthread_kill + 10
1   libsystem_c.dylib               0x926ecf78 pthread_kill + 106
2   libsystem_c.dylib               0x926ddbdd abort + 167
3   libsystem_c.dylib               0x92701508 szone_error + 333
4   libsystem_c.dylib               0x92702dd1 free_small_botch + 102
5   com.apple.CoreFoundation        0x97ee51e8 __CFAllocatorSystemDeallocate + 24
6   com.apple.CoreFoundation        0x97ee51ba CFAllocatorDeallocate + 266 
7   com.apple.CoreFoundation        0x97ee50a2 __CFStrDeallocateMutableContents + 178
8   com.apple.CoreFoundation        0x97ee422b __CFStringChangeSizeMultiple + 3147
9   com.apple.CoreFoundation        0x97f86010 __CFStringCheckAndReplace + 496
10  com.apple.CoreFoundation        0x97f95dad -[__NSCFString appendString:] + 45
11  com.TopTestDFU                  0x00109f6d -[AppController(RS232RW) 
threadRS232Read:] + 752
12  com.apple.Foundation            0x92aabf7d -[NSThread main] + 45 
13  com.apple.Foundation            0x92aabf2d __NSThread__main__ + 1582
14  libsystem_c.dylib               0x926eaed9 _pthread_start + 335
15  libsystem_c.dylib               0x926ee6de thread_start + 34
4

1 に答える 1

0

NSMutableString などの Cocoa 可変オブジェクトは、スレッドセーフではありません。何らかの形式のロックを使用して同期を調整するのはあなた次第です。

1 つのオプションとして NSLock を確認してください。

4 つの NSMutableStrings を ivar ではなくアトミック プロパティにしてみてください。この場合はうまくいくかもしれませんが、アトミックは実際にはスレッドの安全性を保証していません。

[編集] ...実際には、あなたの場合、各スレッドが異なるポート番号を使用していると確信している場合、問題はおそらく NSMutableStrings ではありません。NSString *buffStr = [NSString stringWithUTF8String:buff];別のスレッドが buffStr の追加を完了する前に、あるスレッドによって呼び出されている可能性があります。したがって、それと追加の周りにロックが必要です。

于 2013-05-10T14:46:09.970 に答える