我一直面临这个问题,我承认我缺乏一些内存管理的基本概念。我无法解决这个问题并相信我,我一直在尝试这么多事情。
在我的应用程序中,有4个线程(将来最多可以有12个线程),它们将从RS232端口读取。在每个线程(threadRS232Read
)中,我将使用appendString将RS232字符附加到相应的NSMutableString中。使用appendString,NSMutableString将变得非常大,直到完整测试完成。并且在测试中定期调用clearRdBuffStr
来清除字符串。应用程序总是在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中崩溃。
崩溃日志如下:
....
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
答案 0 :(得分:0)
Cocoa可变对象(如NSMutableString)不是线程安全的。您可以使用某种形式的锁来安排同步。
查看NSLock的一个选项。
您可以尝试将4个NSMutableStrings转换为原子属性而不是ivars。它可能在这种情况下有效,尽管原子并不能保证线程安全。
[编辑]
...实际上,如果在您的情况下,您确定每个线程使用的是不同的端口号,那么可能不是NSMutableStrings就是问题所在。在另一个线程完成附加buffStr之前,可能NSString *buffStr = [NSString stringWithUTF8String:buff];
正在调用{{1}}。所以你需要锁定它以及追加。