典型崩溃问题集锦

简介: 典型崩溃问题集锦

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


目录
相关文章
|
Java Spring
使用 Spring Boot 多个定时任务阻塞问题的解决方案
我是小假 期待与你的下一次相遇 ~
660 5
|
消息中间件 设计模式 运维
从三万英尺看全链路灰度
从本期开始,我们将通过《全链路灰度:自顶向下的方法》的系列文章,由远及近的剖析全链路灰度全貌,系列文章分为4篇: 《从三万英尺看全链路灰度》、《从三千英尺看全链路灰度》、《从三百英尺看全链路灰度》、《总结篇》。敬请关注!
从三万英尺看全链路灰度
|
4天前
|
存储 弹性计算 缓存
阿里云服务器租赁费用:新版租赁收费标准及活动报价参考
本文更新了2026年阿里云全系列云服务器租赁活动报价,所有特惠资源均可前往阿里云活动中心选购,整体覆盖从个人入门到企业级高性能场景的全梯度需求。其中轻量应用服务器主打极致性价比,2核2G峰值200M带宽配置每日10点、15点限时抢购价仅38元/年,2核4G配置379元/年起;高性价比的经济型e实例、通用算力型u2i实例覆盖2核4G至4核32G全档位,适配开发测试与中小型企业业务;搭载英特尔至强6处理器的第九代c9i企业级实例算力较上代提升20%,支撑高并发生产环境,不同实例规格价差清晰,用户可根据自身业务负载与预算灵活选型。
1494 110
|
11天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1936 8
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
5天前
|
人工智能 程序员 API
Codex 接入 DeepSeek-V4-Flash:还能补上识图,提供两套方案
Codex 接入 DeepSeek-V4-Flash 怎么配?本文覆盖 CLI 与桌面端,再用 qwen3-vl-flash 补识图,两套方案可直接照做
|
4天前
|
编解码 人工智能 安全
2核4G/4核8G/8核16G阿里云服务器如何选择实例?经济型e、通用算力型u2i与计算型c9i选哪个?
本文介绍了阿里云2核4G、4核8G、8核16G三档主流配置下经济型e、通用算力型u2i和计算型c9i三种实例的最新活动价格与适用场景。同配置下三者价差显著,以2核4G为例,经济型e低至599.93元/年,计算型c9i则高达1742.08元/年。文章详细解析了各实例的性能定位:经济型e适合轻负载入门场景,u2i兼顾稳定算力与性价比,c9i凭借第9代至强处理器与芯片级安全能力支撑高性能业务。同时提示用户可叠加满减优惠券享受折上折,建议根据业务负载与预算综合决策。
517 112
|
9天前
|
存储 人工智能 关系型数据库
阿里云AI产品与云产品最新组合套餐:Token Plan、AI coding及云服务器和建站等组合优惠价
阿里云推出全新“算力+模型+应用”一站式云与AI组合套餐活动,覆盖从个人开发者到中大型企业的全场景需求。核心亮点为分三档定价的Token Plan订阅服务,支持Qwen3.8-Max-Preview大模型调用,错峰时段最低可享0.2折优惠。活动同步推出AI Coding、智能体部署、云电脑托管、0代码建站等十余类场景化组合,搭配99元/年的普惠云服务器、88元/年的入门数据库等经典特惠产品,还为企业提供1V1定制化AI转型方案,大幅降低了不同用户群体拥抱AI的技术门槛与采购成本。
703 111
|
17天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
2307 3