典型崩溃问题集锦

简介: 典型崩溃问题集锦

1.// if(0 == [GlobalShare getGlobalShare].user.driverTypes.length)

// {

// onCompletion(nil);

// return;

// }

NSMutableDictionary *dic = [NSMutableDictionary new];

[dic setObject:[GlobalShare getGlobalShare].user.driverTypes forKey:@”driverTypes”];

设置字典时[GlobalShare getGlobalShare].user.driverTypes 为空,导致设置的值为nil,导致崩溃。

2. for (NSDictionary *dic in self.bookOrderArray)

{

int a = [dic[@”id”] intValue];

if (a == [dict[@”orderId”]intValue])

{

// [deletetArray addObject:dic];

[self.bookOrderArray removeObject:dic];

// flag = YES;

// break;

// [self.bookOrderArray removeObject:dic];

// [self.tableView reloadData];

}

}


// for (NSDictionary *dic in deletetArray)

// {

// [self.bookOrderArray removeObject:dic];

// flag = YES;

// // int a = [dic[@”id”] intValue];

// // if (a == [dict[@”orderId”]intValue])

// // {

// // [self.bookOrderArray removeObject:dic];

// // [self.tableView reloadData];

// // }

// }

正遍历数组时删除本可变数组的元素,导致数组个数减少而崩溃。解决访问,先把需要删除的元素放到一个临时删除数组里,然后删除。若一次只删除一个元素只需要直接删除并结束遍历就可以了。

3.

-(void)saveCoordates

{

FLDDLogDebug(@”函数”);

if(-1 != _processingOrderId)

{

NSMutableArray *arr = nil;

NSString *str = nil;

NSString *path = nil;

NSData *data = nil;

NSUInteger count = 0;

path = [Singleton filePath:(NSString *)g_coordatesPath];

if(_canModifyCoordatesFlag && _saveCoordatesFlag)

{

return;

}

_canModifyCoordatesFlag = YES;

_saveCoordatesFlag = YES;

count = _coordates.count;

if(count > 0)

{

if(_saveCoordatesIndex >= count)

{

_saveCoordatesIndex = count;

}

NSMutableArray *coordatesData = [NSMutableArray arrayWithArray:_coordates];

_canModifyCoordatesFlag = NO;

        data=[NSData dataWithContentsOfFile : path];
        arr = [NSMutableArray arrayWithArray:coordatesData];
        NSUInteger i = _saveCoordatesIndex;
        for (; i < count; i++)
        {

            CLLocation* location = arr[i];
            if([location isKindOfClass:[CLLocation class]])
            {
                if(0 == str.length)
                {
                    str = [NSString stringWithFormat:@"%.6f,%.6f", location.coordinate.latitude,location.coordinate.longitude];
                }
                else
                {
                    str = [NSString stringWithFormat:@"%@\n%.6f,%.6f", str,location.coordinate.latitude,location.coordinate.longitude];
                }
            }
        }
        _saveCoordatesIndex = i;

    }
    else
    {
        _usingCoordatesFlag = NO;
    }

    FLDDLogDebug(@"str:%@", str);
    if(0 == str.length)
    {
        return;
    }
    else if(0 == data.length)
    {
        data = [str dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
        [data writeToFile:path atomically:YES];
    }
    else
    {
        str = [NSString stringWithFormat:@"\n%@", str];
        NSData *dataTemp = [str dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
        NSMutableData *mutableData = [NSMutableData alloc];
        [mutableData appendData:data];
        [mutableData appendData:(NSData *)dataTemp];
        [mutableData writeToFile:path atomically:YES];
    }
    _saveCoordatesFlag = NO;

    FLDDLogDebug(@"path:%@", path);

}

}

一个子线程正访问可变经纬度数组时,定位代理触发经纬数组增加或用户触发删除经纬数组的所有元素导致,数组越界,该例子已经解决。解决方案,操作可变数组时先用NSMutableArray *coordatesData = [NSMutableArray arrayWithArray:_coordates];拷贝出来一份,使用完后替换原来的数组就可以了。当然想更安全些可以设置访问和删除标识。

4.

@property(nonatomic, assign) NSString *cityCode;


-(id)initWithCoder:(NSCoder *)aDecoder

{

if (self=[super init])

{

    self.cityCode = [aDecoder decodeObjectForKey:@"cityCode"];
}
return self;

}


-(id)initWithDictionary:(NSDictionary*)dic

{

if (self=[super init])

{

self.cityCode = [NSString stringWithFormat:@”%@”,dic[@”cityCode”] ==NULL?@”“:dic[@”cityCode”]];

}

return self;

}

-(void)encodeWithCoder:(NSCoder *)aCoder

{

[aCoder encodeObject:self.cityCode forKey:@"cityCode"];

}


在单例子中用assign声明的字符串变量,在多次便解码时,实际上可能被释放掉,导致内存越界访问,进而编解码时崩溃。

/*******************************************************************

函数: (NSString )getCorrectTelStr : (NSString )string

描述: 字符串格式化处理

调用:

被调用: ((NSString )getTextFieldStr : (NSString )string : (NSString *)textFieldValue

返回值:

其它: 调用者保证字符串为空的情况,减少重复检查参数

********************************************************************/

+ (NSString )getCorrectTelStr : (NSString )string

{

//多一个字符位为了保证能放下增加空格的字符串

NSString *str = [[NSString alloc] initWithString:[NSString stringWithFormat:@”%@%@”, string, @”1”]];

char tel_char = (char )[str UTF8String];

char newTel_char = (char )[string UTF8String];

// char tel_char[12] = {0};

// char newTel_char[14] = {0};

char c;

NSInteger i, j, len;

memset(newTel_char, 0, strlen(newTel_char));

len = strlen(tel_char);

j = 0;
for(i = 0; i < len - 1; i++)
{
    c = tel_char[i];
    if(c != ' ')
    {
        newTel_char[j++] = c;
    }

}

memset(tel_char, 0, len);
j = 0;
for(i = 0; i < strlen(newTel_char); i++)
{
    c = newTel_char[i];
    tel_char[j++] = c;

    if((i == 2) || (i == 6))
    {
        tel_char[j++] = ' ';
    }
}


return [[NSString alloc] initWithString:[NSString stringWithFormat:@"%s", tel_char]];

}

NSString和字符数组的转换异常,会死在memset(newTel_char, 0, strlen(newTel_char));这个地方,iphone4s测试出的。

5.

// 下线

- (void)OffLine

{

FLDDLogDebug(@”函数”);

FLDDLogDebug(@”offLine”);


// long long sno = [SingleAsyncSocket sharedInstance].socketThreadSno;

// if(-1 != sno)

// {

// dispatch_sync(dispatch_get_main_queue(), ^{

// // [[SingleAsyncSocket sharedInstance] endSocket];

kill((pid_t)sno, SIGKILL);

// pthread_kill((__bridge pthread_t)([SingleAsyncSocket sharedInstance].socketThread), SIGQUIT);

[[SingleAsyncSocket sharedInstance].socketThread cancel];

// });

//

// }

//

// return;

if([[SingleAsyncSocket sharedInstance] getHitOnOffLineTime] > 0)

{

FLDDLogDebug(@”下线中…”);

[SVProgressHUD showErrorWithStatus:@”下线中…” ];

return;

}

// 发送网络请求 - 下线请求

[SVProgressHUD show];

[[SingleAsyncSocket sharedInstance] socketOffLineClose:^(BOOL successed) {
    [SVProgressHUD dismiss];
    FLDDLogDebug(@"下线成功");
    [[SingleObject sharedInstance] setOffLineFlag:YES];

// if(![[SingleObject sharedInstance] getUseBookOrderVoiceArrayFlag])

// {

// [[SingleObject sharedInstance] setUseBookOrderVoiceArrayFlag:YES];

// if(100 != [[SingleObject sharedInstance] getProgress])

// {

// [[SingleObject sharedInstance] stopSpeaking];

// }

// if([[SingleObject sharedInstance] getBookOrderVoiceArray].count > 0)

// {

// [[SingleObject sharedInstance] removeBookOrderVoiceArray];

// }

// [[SingleObject sharedInstance] setUseBookOrderVoiceArrayFlag:NO];

// }

    if([SingleObject sharedInstance].playBookingFlag)
    {
        [[SingleObject sharedInstance] stopSpeaking];
    }
    else if([SingleObject sharedInstance].playRealOrderFlag)
    {
        [[SingleObject sharedInstance] StopVoice];
    }

// [[NSNotificationCenter defaultCenter] removeObserver:self name:NEW_ORDER_NOTIFICATION object:nil];

// [[NSNotificationCenter defaultCenter] removeObserver:self name:NEW_ORDER_TIMEOUT_NOTIFICATION object:nil];

// [[NSNotificationCenter defaultCenter] removeObserver:self name:LOAD_MAP_NOTIFICATION object:nil];

// [[NSNotificationCenter defaultCenter] removeObserver:self name:ORDER_FEE_CHANGE_NOTIFICATION object:nil];

// [[NSNotificationCenter defaultCenter] removeObserver:self name:PASSENGER_CANCEL_ORDER_NOTIFICATION object:nil];

// [[NSNotificationCenter defaultCenter] removeObserver:self name:@”applicationWillEnterForegroundNotification” object:nil];

// [[NSNotificationCenter defaultCenter] removeObserver:self name:OFF_LINE_MAINVIEWCONTROLLER_NOTIFICATION object:nil];

[servicingView removeFromSuperview];

[[Singleton sharedInstance] setLoginOrderStat : LOGIN_ORDER_STATE_OFFLINE];

[self.navigationController popViewControllerAnimated:YES];

// [[SingleObject sharedInstance] setNeedPlayRealOrderFlag:NO];

[[SingleObject sharedInstance] setPlayRealOrderFlag:NO];

// [self.navigationController popToRootViewControllerAnimated:NO];

} onfailCompltion:^(BOOL successed) {

FLDDLogDebug(@”下线失败”);

//非常抱歉,连接出现问题

[SVProgressHUD showErrorWithStatus:@”非常抱歉,连接出现问题” ];

}];

FLDDLogDebug(@”下线”);


}


当一个线程发送了通知,这个地图页面对通知进行了处理,当它回到上一层页面需要显示移除通知,不然再次进入可能收到两个通知,也可能引起崩溃。


6.

- (void)SelectCarTypeWithButton:(UIButton *)sender

{

FLDDLogDebug(@”函数”);

// if (_isSelect[sender.tag - 901])

if (_isSelect[sender.tag])

{

[sender setImage:[UIImage imageNamed:@”接单(未勾选)”] forState:UIControlStateNormal];

NSString *driverTypes = [GlobalShare getGlobalShare].user.driverTypes;

[driverTypesDict removeObjectForKey:[_carTypeDict valueForKey:[NSString stringWithFormat:@”%ld”,(long)sender.tag]]];

if(0 == driverTypes.length)

{

driverTypes = [NSString stringWithFormat:@”%ld”,(long)sender.tag - 900];

}

else

{

NSString *str = nil;

NSArray *values = [driverTypesDict allValues];

for(int i = 0; i < values.count; i++)

{

if(nil == str)

{

str = [NSString stringWithFormat:@”%@”, values[i]];

}

else

{

str = [NSString stringWithFormat:@”%@:%@”, str, values[i]];

}

}

        if(str.length > 0)
        {
            driverTypes = str;
        }

    }
    [GlobalShare getGlobalShare].user.driverTypes = driverTypes;
    [[GlobalShare getGlobalShare] saveinfo:([GlobalShare getGlobalShare].user)];
    FLDDLogDebug(@"driverTypes:%@", driverTypes);
}
else
{
    [sender setImage:[UIImage imageNamed:@"接单(勾选)"] forState:UIControlStateNormal];
    _currentCarType = [_carTypeDict objectForKey:[NSString stringWithFormat:@"%ld",(long)sender.tag]];
    [_selectCarType addObject:_currentCarType];
    NSString *driverTypes = [GlobalShare getGlobalShare].user.driverTypes;
    FLDDLogDebug(@"value: %@", [NSString stringWithFormat:@"%ld",(long)sender.tag - 900]);
    FLDDLogDebug(@"key: %@", [_carTypeDict valueForKey:[NSString stringWithFormat:@"%ld",(long)sender.tag]]);

    [driverTypesDict setObject:[NSString stringWithFormat:@"%ld",(long)sender.tag - 900] forKey:[_carTypeDict valueForKey:[NSString stringWithFormat:@"%ld",(long)sender.tag]]];
    if((nil == driverTypes) || !([driverTypes isKindOfClass:[NSString class]]))
    {
        if(0 != user.serviceType)
        {
            driverTypes = [NSString stringWithFormat:@"%d",user.serviceType];
            [[GlobalShare getGlobalShare] saveinfo:[GlobalShare getGlobalShare].user];
        }
        else
        {
            return;
        }

    }
    if(0 == driverTypes.length)
    {
        driverTypes = [NSString stringWithFormat:@"%ld",(long)sender.tag - 900];
    }
    else
    {
        NSString *str = nil;
        NSArray *values = [driverTypesDict allValues];
        for(int i = 0; i < values.count; i++)
        {
            if(nil == str)
            {
                str = [NSString stringWithFormat:@"%@", values[i]];
            }
            else
            {
                str = [NSString stringWithFormat:@"%@:%@", str, values[i]];
            }
        }

        if(str.length > 0)
        {
            driverTypes = str;
        }
    }
    [GlobalShare getGlobalShare].user.driverTypes = driverTypes;
    [[GlobalShare getGlobalShare] saveinfo:([GlobalShare getGlobalShare].user)];
    FLDDLogDebug(@"driverTypes:%@", driverTypes);

}
_isSelect[sender.tag - 901] = !_isSelect[sender.tag - 901];

}

访问数组时下标控制错误或传入的下标超过数组的实际大小,导致数组崩溃,有时候这种数组越界由于ios内部字节对齐等原因有概率出啊线不是立即,而是有时候进入其它页面时崩溃。

7.加载表格时经常出现数组访问或访问空指针,编辑表格后没有结束编译的崩溃。这个就不多说了。


目录
相关文章
|
3月前
|
开发者 缓存 数据库
【性能奇迹】Wicket应用的极速重生:揭秘那些让开发者心跳加速的调优秘技!
【8月更文挑战第31天】在软件开发中,性能优化是确保应用快速响应和高效运行的关键。本书《性能调优:Apache Wicket应用的速度提升秘籍》详细介绍了如何优化Apache Wicket应用,包括代码优化、资源管理、数据库查询优化、缓存策略及服务器配置等方面。通过减少不必要的组件渲染、优化SQL查询、使用缓存和调整服务器设置等方法,本书帮助开发者显著提升Wicket应用的性能,确保其在高并发和数据密集型场景下的稳定性和响应速度。
44 0
|
4月前
|
消息中间件 Android开发 开发者
🔍深度剖析Android内存泄漏,让你的App远离崩溃边缘,稳如老狗!🐶
【7月更文挑战第28天】在 Android 开发中,内存管理至关重要。内存泄漏可悄无声息地累积,最终导致应用崩溃或性能下滑。它通常由不正确地持有 Activity 或 Fragment 的引用引起。常见原因包括静态变量持有组件引用、非静态内部类误用、Handler 使用不当、资源未关闭及集合对象未清理。使用 Android Studio Profiler 和 LeakCanary 可检测泄漏,修复方法涉及使用弱引用、改用静态内部类、妥善管理 Handler 和及时释放资源。良好的内存管理是保证应用稳定性的基石。
78 4
|
4月前
|
测试技术
ACL 2024:大模型性能掺水严重?北大交出答卷:交互评估+动态出题,死记硬背也没用
【7月更文挑战第8天】北大研究团队推出KIEval框架,针对大语言模型(LLMs)的性能评估进行创新。KIEval采用互动评估和动态出题,通过多轮基于知识的对话测试模型理解和应用能力,旨在减少数据污染影响,挑战死记硬背的评估。然而,该方法可能增加计算需求,且评估结果可能受主观因素影响,不适用于所有类型LLMs。[论文链接:](https://arxiv.org/abs/2402.15043)**
88 24
|
3月前
|
消息中间件 缓存 前端开发
评论系统如何不崩溃?揭开海量评论背后的技术秘密
小米介绍了一种高效处理海量新闻评论的技术方案。面对突发新闻带来的评论潮,通过采用消息队列异步入库、读写分离以及热点缓存等技术,不仅能有效减轻数据库压力,还能保证用户快速查看最新评论。消息队列如Kafka或RabbitMQ可缓存评论请求,后台异步处理入库,避免数据库过载。读写分离则通过主从数据库架构分散读取负载,配合热点评论的缓存机制进一步提升访问速度。这套架构确保了系统的稳定性和响应速度,适用于高并发的评论处理场景。
52 0
|
6月前
|
缓存 算法 Java
Linux内核新特性年终大盘点-安卓杀后台现象减少的背后功臣MGLRU算法简介
MGLRU是一种新型内存管理算法,它的出现是为了弥补传统LRU(Least Recently Used)和LFU(Least Frequently Used)算法在缓存替换选择上的不足,LRU和LFU的共同缺点就是在做内存页面替换时,只考虑内存页面在最近一段时间内被访问的次数和最后一次的访问时间,但是一个页面的最近访问次数少或者最近一次的访问时间较早,可能仅仅是因为这个内存页面新近才被创建,属于刚刚完成初始化的年代代页面,它的频繁访问往往会出现在初始化之后的一段时间里,那么这时候就把这种年轻代的页面迁移出去
值得一看!阿里又杀疯了开源内部“M9”级别全彩版分布式实战笔记
系统架构大致经历了单体应用架构→垂直应用架构→分布式架构→SOA架构→微服务架构的演变
|
存储 缓存 测试技术
三十、如何迅速分析出系统I/O的瓶颈在哪里?
最容易想到的是存储空间的使用情况,包括容量、使用量以及剩余空间等。我们通常也称这些为磁盘空间的使用量,因为文件系统的数据最终还是存储在磁盘上。
301 0
J3D在UOS+KIRIN崩溃2:深层原因分析
J3D在UOS+KIRIN崩溃2:深层原因分析
65 0
|
存储 NoSQL 算法
完爆 90% 的性能毛病,22 点通用绝招介绍(一)
完爆 90% 的性能毛病,22 点通用绝招介绍(一)
完爆 90% 的性能毛病,22 点通用绝招介绍(一)
|
存储 缓存 运维
完爆 90% 的性能毛病,22 点通用绝招介绍(二)
完爆 90% 的性能毛病,22 点通用绝招介绍(二)
完爆 90% 的性能毛病,22 点通用绝招介绍(二)