简体   繁体   中英

iOS - My app crashes with memory Error if only runs on Device

My app runs perfectly on simulator. But when I run it on device to test, the app crashed.

The displayed error :

"malloc: * error for object 0x17415d0c0: Invalid pointer dequeued from free list * set a breakpoint in malloc_error_break to debug";

And another error sometimes happens :

"Thread 6 com.apple.NSURLConnectionLoader: Program received signal: EXC_BAD_ACCESS"

This two errors are random, it happens after the app runs two or three minutes.

I searched Google and find some solution. It says that set a breakpoint in malloc_error_break to debug, but this only work on simulator. Even I set the malloc_error_break, the app still crush and it does not display anything, I only can see that error message.

This is big project, I really do not know which part of the code cause the problem and which part of the code I need to post. But I have doubt with one of the class, my 'SynchroningView'. This view will be displayed if only my app make synchronisation with the server. It means this view is included in almost all the Viewcontroller in my project.

Here is my 'SynchroningView' class:

"SynchroningView.h"

#import <UIKit/UIKit.h>
@class SynchroningView;

@protocol SynchroningViewDelegate
@optional
- (void)SynchroningViewCancelButtonDidClicked:(SynchroningView *)synchroningView;
- (void)SynchroningViewStartTherapyButtonDidClicked:(SynchroningView *)synchroningView;
@end



@interface SynchroningView : UIView <DataManagerDelegate>

@property (nonatomic, assign) id<SynchroningViewDelegate>delegateCustom;

@property (nonatomic, retain) UIButton *containerButton;

@property (nonatomic, retain) Patient *singlePatient;





- (instancetype)initWithFrame:(CGRect)frame;

- (void)showInView:(UIView *)view;

- (void)dismissMenuPopover;

@end

SynchroningView.m

#import "SDDemoItemView.h"
#import "SDPieLoopProgressView.h"



#define Directory_Document  [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]

#define FileName_Image_SynchroningView_BackGroundImageName @"SynchroningView_BackGroundImage"

#define FilePath_Image_SynchroningView_BackGroundImageName [Directory_Document stringByAppendingPathComponent:FileName_Image_SynchroningView_BackGroundImageName]



@interface SynchroningView ()

@property   (nonatomic, strong) DataManager*    dataManager;

@property   (nonatomic, retain) UILabel*    messageLabel;

@property   (nonatomic, retain) UIButton*   CancelButton;
@property   (nonatomic, retain) CoolButton* ConfirmButton;
@property   (nonatomic, retain) CoolButton* startTherapyButton;

@property   (nonatomic, strong) SDDemoItemView* demoProgressView;

@end

@interface SynchroningView ()
{
    BOOL    _blinking;

    NSTimer *timer;
}
@end

@implementation SynchroningView

-(void)dealloc
{

}
//get the background Image, make it blur and save it. In this way I do not have to use Blur function everytim, I use the blured image directly
- (UIImage *)getBackGroundImage
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:FilePath_Image_SynchroningView_BackGroundImageName]) {
        return [UIImage imageWithContentsOfFile:FilePath_Image_SynchroningView_BackGroundImageName];
    }
    else{
        UIImage *backImage = [UIImage imageWithContentsOfFile:kBackgroundImagePath];
        backImage = [backImage blurWithFloat:20.0f];

        NSData * binaryImageData = UIImagePNGRepresentation(backImage);

        if ([binaryImageData writeToFile:FilePath_Image_SynchroningView_BackGroundImageName atomically:YES]) {
            return backImage;
        }
    }


    return [UIImage imageWithContentsOfFile:kBackgroundImagePath];
}

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self) {

        _blinking = NO;
        self.dataManager = [[DataManager alloc] init];
        self.dataManager.DelegateCustom = self;



        self.backgroundColor = [UIColor clearColor];






        self.containerButton = [[UIButton alloc] init];
        [self.containerButton setBackgroundColor:RGBA_Custom(0, 0, 0, 0.6f)];
        [self.containerButton setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin];




        UIView *shadowView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
        [self addSubview:shadowView];
        shadowView.backgroundColor = RGBA_Custom(230, 249, 251, 0.96f);
//        shadowView.layer.borderWidth = 2*IPAD;
//        shadowView.layer.borderColor = [RGBA_Custom(199, 199, 199, 1.0f) CGColor];
        shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
        shadowView.layer.shadowOpacity = 0.4;
        shadowView.layer.shadowRadius = 4*IPAD;
        shadowView.layer.shadowOffset = CGSizeMake(4.0f*IPAD, 4.0f*IPAD);
        shadowView.layer.cornerRadius = 6*IPAD;
        shadowView.userInteractionEnabled = NO;




        UIImageView *backGround = [[UIImageView alloc] initWithImage:[self getBackGroundImage]];
        backGround.frame = CGRectMake(0, 0, shadowView.frame.size.width, shadowView.frame.size.height);
        backGround.backgroundColor = [UIColor clearColor];
        [shadowView addSubview:backGround];
        backGround.layer.cornerRadius = shadowView.layer.cornerRadius;
        backGround.layer.masksToBounds = YES;




        ImageWIDTH_ = self.frame.size.height*0.3;
        self.demoProgressView =[SDDemoItemView demoItemViewWithClass:[SDPieLoopProgressView class]];
        self.demoProgressView.frame = CGRectMake((self.frame.size.width - ImageWIDTH_)/2,
                                                 kFromLeft,
                                                 ImageWIDTH_,
                                                 ImageWIDTH_);
        [self addSubview:self.demoProgressView];




        self.messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(kFromLeft,
                                                                  self.demoProgressView.frame.origin.y + self.demoProgressView.frame.size.height + kFromLeft,
                                                                  self.frame.size.width - kFromLeft*2,
                                                                  self.frame.size.height - (self.demoProgressView.frame.origin.y + self.demoProgressView.frame.size.height + kFromLeft*2))];
        self.messageLabel.backgroundColor = [UIColor clearColor];
        self.messageLabel.textColor = [UIColor blackColor];
        self.messageLabel.textAlignment = NSTextAlignmentCenter;
        self.messageLabel.numberOfLines = 0;
        self.messageLabel.lineBreakMode = NSLineBreakByWordWrapping;
        self.messageLabel.font = [UIFont boldSystemFontOfSize:kIPAD ? 20:12];
        self.messageLabel.text = @"";
        self.messageLabel.adjustsFontSizeToFitWidth = YES;
        [self addSubview:self.messageLabel];









        CGFloat BtnHeight = kIPAD ? 40  : 30;
        self.CancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
        self.CancelButton.frame = CGRectMake(self.frame.size.width - kFromLeft*0.5 - BtnHeight,
                                             kFromLeft*0.5,
                                             BtnHeight,
                                             BtnHeight);
        self.CancelButton.backgroundColor = [UIColor clearColor];
        [self.CancelButton setImage:[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"utilities_close" ofType:@"png"]] forState:UIControlStateNormal];
        [self.CancelButton addTarget:self action:@selector(pressCancelButton:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.CancelButton];




        BtnHeight = kIPAD ? 70  : 50;
        CGFloat BtnWidth  = self.frame.size.width/4;
        NSString*   ConfirmButtonStr = NSLocalizedString(@"Confirm", nil);
        ExpectedSize = [ConfirmButtonStr sizeWithFont:self.messageLabel.font constrainedToSize:CGSizeMake(VIEW_WIDTH, BtnHeight) lineBreakMode:NSLineBreakByWordWrapping];
        ExpectedSize = CGSizeMake(ExpectedSize.width + 30*IPAD, ExpectedSize.height);
        self.ConfirmButton = [CoolButton buttonWithType:UIButtonTypeCustom];
        self.ConfirmButton.frame = CGRectMake((self.frame.size.width - ExpectedSize.width)/2,
                                              self.frame.size.height - BtnHeight - kFromLeft,
                                              ExpectedSize.width,
                                              BtnHeight);
        self.ConfirmButton.titleLabel.font = self.messageLabel.font;
        [self.ConfirmButton setTitle:ConfirmButtonStr forState:UIControlStateNormal];
        [self.ConfirmButton addTarget:self action:@selector(pressConfirmButton:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.ConfirmButton];








        BtnWidth = self.frame.size.width*0.6;
        NSString*   startTherapyButtonStr = NSLocalizedString(@"StartTerapia", nil);
        ExpectedSize = [startTherapyButtonStr sizeWithFont:self.messageLabel.font constrainedToSize:CGSizeMake(VIEW_WIDTH, BtnHeight) lineBreakMode:NSLineBreakByWordWrapping];
        ExpectedSize = CGSizeMake(ExpectedSize.width + 30*IPAD, ExpectedSize.height);
        self.startTherapyButton = [CoolButton buttonWithType:UIButtonTypeCustom];
        self.startTherapyButton.frame = CGRectMake((self.frame.size.width - ExpectedSize.width)/2,
                                                   self.ConfirmButton.frame.origin.y,
                                                   ExpectedSize.width,
                                                   self.ConfirmButton.frame.size.height);
        self.startTherapyButton.titleLabel.font = self.messageLabel.font;
        [self.startTherapyButton setTitle:startTherapyButtonStr forState:UIControlStateNormal];
        [self.startTherapyButton addTarget:self action:@selector(startTherapyButtonDidClicked:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.startTherapyButton];





        self.CancelButton.alpha         = 0.0;
        self.ConfirmButton.alpha        = 0.0;
        self.startTherapyButton.alpha   = 0.0;





        if (self.dataManager.firstSynchronizationAgain == 1 && [AccessedInfo getAccessedInfo]) {
            UILabel *alertInfoLabel = [[UILabel alloc] initWithFrame:CGRectMake(kFromLeft,
                                                                                0,
                                                                                self.frame.size.width - kFromLeft*2,
                                                                                VIEW_HEIGHT)];
            alertInfoLabel.backgroundColor = [UIColor clearColor];
            alertInfoLabel.textColor = COLOR_CIRCLE;
            alertInfoLabel.textAlignment = NSTextAlignmentCenter;
            alertInfoLabel.numberOfLines = 0;
            alertInfoLabel.lineBreakMode = NSLineBreakByWordWrapping;
            alertInfoLabel.font = [UIFont systemFontOfSize:self.startTherapyButton.titleLabel.font.pointSize-2];
            alertInfoLabel.text = NSLocalizedString(@"SynchronizingNew", nil);
            ExpectedSize = [alertInfoLabel.text sizeWithFont:alertInfoLabel.font constrainedToSize:alertInfoLabel.frame.size lineBreakMode:NSLineBreakByWordWrapping];
            alertInfoLabel.frame = CGRectMake(alertInfoLabel.frame.origin.x,
                                              self.startTherapyButton.frame.origin.y - ExpectedSize.height - IPAD*2,
                                              alertInfoLabel.frame.size.width,
                                              ExpectedSize.height);
            [self addSubview:alertInfoLabel];

        }





        [self.containerButton addSubview:self];
    }

    return self;
}
//show the synchronization result message
- (void)setMessageLabelString:(NSString *)labelName
{
    self.messageLabel.text = labelName;
    ExpectedSize = [labelName sizeWithFont:self.messageLabel.font constrainedToSize:CGSizeMake(self.messageLabel.frame.size.width, VIEW_HEIGHT) lineBreakMode:NSLineBreakByWordWrapping];
    self.messageLabel.frame = CGRectMake(self.messageLabel.frame.origin.x,
                                     self.messageLabel.frame.origin.y,
                                     self.messageLabel.frame.size.width,
                                     ExpectedSize.height);


    timer = [NSTimer scheduledTimerWithTimeInterval:0.8 target:self selector:@selector(MessageLabelBlinking) userInfo:nil repeats:YES];

//    self.messageLabel.adjustsFontSizeToFitWidth = YES;
}
- (void)MessageLabelBlinking
{
    if (_blinking) {
        NSString *threeDot = @".....";
        if ([self.messageLabel.text rangeOfString:threeDot].location == NSNotFound) {
            self.messageLabel.text = [self.messageLabel.text stringByAppendingString:@"."];
        }
        else{
            self.messageLabel.text = [self.messageLabel.text stringByReplacingOccurrencesOfString:threeDot withString:@""];
        }
    }
    else{
        [timer invalidate];
        timer = nil;
    }
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
//init the data processing block
- (void)initCustomOtherParameters
{
    self.dataManager.DelegateCustom = self;

    self.dataManager.blockProcessingData = ^(float allCommand, float restCommand){
        if (allCommand == 0) {
            [[SingletonOperationQueue mainQueue] addOperationWithBlock:^{
                self.demoProgressView.progressView.progress = 1;
                NSString *messageStr = [NSLocalizedString(@"SuccessfulSynchronized", nil) stringByAppendingFormat:@"\n%@", NSLocalizedString(@"EmptyTherapy", nil)];
                [self setMessageLabelString:messageStr];
                _blinking = NO;
                self.CancelButton.alpha         = 1.0;
            }];
        }
        else{
            float percenAger = (restCommand/allCommand);
            percenAger = 1 - percenAger;

            [[SingletonOperationQueue mainQueue] addOperationWithBlock:^{
                self.demoProgressView.progressView.progress = percenAger;
                if (restCommand == 0) {
                    [self downloadZipFile];
                }
            }];
        }
    };

    [Patient RemovePatient];

    [self.singlePatient SavePatient];
}
- (void)showInView:(UIView *)view
{
    self.transform = CGAffineTransformScale(self.transform, 0.8, 0.8);

    self.containerButton.alpha = 0.0f;
    self.containerButton.frame = view.bounds;

    [view addSubview:self.containerButton];

    [UIView animateWithDuration:0.15 animations:^{
        self.containerButton.alpha = 1.0f;
        self.transform = CGAffineTransformScale(self.transform, 1.4, 1.4);

    }completion:^(BOOL finished) {
        if (finished) {
            [UIView animateWithDuration:0.20 animations:^{
                self.transform = CGAffineTransformIdentity;
            }];

            [self sendConnectionTestRequest];
        }
        else{
            self.transform = CGAffineTransformIdentity;
            [self sendConnectionTestRequest];
        }
    }];
}
- (void)dismissMenuPopover
{
    [self hide];
}
- (void)hide
{
    [UIView animateWithDuration:0.25 animations:^{
        self.transform = CGAffineTransformScale(self.transform, 0.8, 0.8);
        self.containerButton.alpha = 0.0f;
    }completion:^(BOOL finished) {
        if (finished) {
            [self.containerButton removeFromSuperview];
        }
    }];
}

- (void)pressCancelButton:(UIButton *)button
{
    [self.dataManager CommunicationCancel];

    [self.delegateCustom SynchroningViewCancelButtonDidClicked:self];
}
- (void)startTherapyButtonDidClicked:(UIButton *)button
{
    [self.delegateCustom SynchroningViewStartTherapyButtonDidClicked:self];
}
- (void)pressConfirmButton:(UIButton *)button
{
    [UIView animateWithDuration:0.25 animations:^{
        self.CancelButton.alpha  = 0.0;
        self.ConfirmButton.alpha = 0.0;
    }];



    [self sendRegistrationRequestConfirm:YES];
}
#pragma mark - Communication
- (void)sendConnectionTestRequest
{
    [self initCustomOtherParameters];

    _blinking = YES;

    [self setMessageLabelString:NSLocalizedString(@"StartRegistration", nil)];

    [self.dataManager sendRequestCommand:kConnectionTest];
}
- (void)sendRegistrationRequestConfirm:(BOOL)Confirm
{
    [self setMessageLabelString:NSLocalizedString(@"StartRegistration", nil)];
    NSString *registrationResult = [self.dataManager RegisterTheUSER_Confirm:Confirm];
    [self processLogInResult:registrationResult];
}
- (void)processLogInResult:(NSString *)logInResult
{
    if ([logInResult isEqual:@"1"]) {
        if ([self.dataManager DataInitialization]) {
            [self.dataManager DataInitializationForFakeUser];

            [self.singlePatient SavePatient];

            [self startTherapyButtonDidClicked:nil];
        }
    }
    else if ([logInResult isEqual:@"2"]) {
        if ([self.dataManager DataInitialization]) {
            self.singlePatient.record7_AuthenticatedUser = YES;

            [self.singlePatient SavePatient];

            [self.dataManager sendRequestCommand:kNewDataAvailable];
        };
    }
    else if ([logInResult intValue] == DEVICE_NOT_REGISTERED){
        logInResult = NSLocalizedString(@"105", nil);
        _blinking = NO;
        [self setMessageLabelString:logInResult];
        [UIView animateWithDuration:0.25 animations:^{
            self.CancelButton.alpha  = 1.0;
            self.ConfirmButton.alpha = 1.0;
        }];
    }
    else if ([logInResult isEqualToString:kNO]){
        _blinking = NO;
        [self setMessageLabelString:@"Cannot find the Error "];
        [UIView animateWithDuration:0.25 animations:^{
            self.CancelButton.alpha  = 1.0;
        }];
    }
    else{
        _blinking = NO;
        [self setMessageLabelString:logInResult];
        [UIView animateWithDuration:0.25 animations:^{
            self.CancelButton.alpha  = 1.0;
        }];
    }
}

- (void)downloadZipFile
{
    self.demoProgressView.progressView.progress = 1.0;

    sleep(0.4);

    [self setMessageLabelString:NSLocalizedString(@"Loading Data", nil)];
    self.demoProgressView.progressView.progress = 0.0;
    self.dataManager.blockProcessingDataPercentAge = ^(float percentAge, NSString *fileName){

        if ([fileName isEqualToString:kaderenzainfo]) {
            [[SingletonOperationQueue mainQueue] addOperationWithBlock:^{
                self.demoProgressView.progressView.progress = percentAge;
                NSLog(@"%f", percentAge);
                if (percentAge == 0.5) {
                    sleep(0.4);
                    NSString *aderenzainfoFilePath =  [[NSUserDefaults standardUserDefaults] objectForKey:kaccertamentiinfo];
                    [self.dataManager downloadZipFile:aderenzainfoFilePath fileName:kaccertamentiinfo];
                }
            }];
        }
        else if ([fileName isEqualToString:kaccertamentiinfo]){
            [[SingletonOperationQueue mainQueue] addOperationWithBlock:^{
                self.demoProgressView.progressView.progress = 0.5 + percentAge;
                if (0.5 + percentAge >= 1.0) {

                    _blinking = NO;
                    self.CancelButton.alpha = 1.0;

                    if ([Patient getPatient].record_patientStatus == PatientStatusSuspendedType) {
                        [self setMessageLabelString:NSLocalizedString(@"SuspendedPatient", nil)];
                    }
                    else if ([Patient getPatient].record_patientStatus == PatientStatusDeletedType){
                        [self setMessageLabelString:NSLocalizedString(@"DeletedPatient", nil)];
                    }
                    else if ([Patient getPatient].record_patientStatus == PatientStatusActiveType){
                        [self setMessageLabelString:NSLocalizedString(@"SuccessfulSynchronized", nil)];
                        self.startTherapyButton.alpha = 1.0;
                    }
                }
            }];
        }
    };



    NSString *aderenzainfoFilePath =  [[NSUserDefaults standardUserDefaults] objectForKey:kaderenzainfo];
    [self.dataManager downloadZipFile:aderenzainfoFilePath fileName:kaderenzainfo];
}
#pragma mark - DataManagerDelegate
- (void)CommunicationConnectionTest:(BOOL)connected
{
    if (connected) {
        [self sendRegistrationRequestConfirm:NO];
    }
    else{
        [self setMessageLabelString:NSLocalizedString(@"connectionTestFail", nil)];
        [UIView animateWithDuration:0.25 animations:^{
            self.CancelButton.alpha  = 1.0;
        }];
        _blinking = NO;
    }
}
- (void)CommunicationSendRequestCommandName:(NSString *)commandName
{
    if ([commandName isEqualToString:kNewDataAvailable]) {
        [self setMessageLabelString:NSLocalizedString(@"Synchronizing", nil)];
    }
}
- (void)CommunicationReceiveResponseWithOKCommandName:(NSString *)commandName
{

}
- (void)CommunicationReceiveResponseWithRequestError:(NSString *)commandName
{
    [self setMessageLabelString:NSLocalizedString(@"NetworkConnectionError", nil)];
    _blinking = NO;
    [UIView animateWithDuration:0.25 animations:^{
        self.CancelButton.alpha  = 1.0;
    }];
}
- (void)CommunicationReceiveResponseCommandName:(NSString *)commandName WithErrorCode:(int)errorCode withErrorDescription:(NSString *)errorDescription
{
    [self setMessageLabelString:NSLocalizedString(@"NewDataAvaiableErrorCode", nil)];
    _blinking = NO;
    [UIView animateWithDuration:0.25 animations:^{
        self.CancelButton.alpha  = 1.0;
    }];
}
-(void)CommunicationZipFileFailDownload
{
    [self setMessageLabelString:NSLocalizedString(@"ZipFileDownloadFail", nil)];
    _blinking = NO;
    [UIView animateWithDuration:0.25 animations:^{
        self.CancelButton.alpha  = 1.0;
    }];
}
-(void)CommunicationZipFileIsNotReadAble
{
    [self setMessageLabelString:NSLocalizedString(@"ZipFileUnzippedFail", nil)];
    _blinking = NO;
    [UIView animateWithDuration:0.25 animations:^{
        self.CancelButton.alpha  = 1.0;
    }];
}
@end

I solved it finally

Inside my Encryption and Decryption function, I have this:

Byte *buffer    = (Byte*)malloc(asciiDataLength);

After I processed with buffer, I convert it to NSData:

NSData *plainData = [NSData dataWithBytesNoCopy:buffer length:asciiDataLength freeWhenDone:YES];

This code causes my app crushes continuously, I changed it to

NSData *plainData = [NSData dataWithBytes:buffer length:asciiDataLength];
free(buffer);

Then my app never crush again.

So , I have to free the Byte by myself, ARC will not free it for me.

Simulator's memory = Pc's RAM ie 4 or 6 gb etc.
and device have only 1 gb maximum. In Xcode while you run the app, you need to click on Debug Navigator , and then click on Memory, it will display the memory consumption of your app.

To see the Leakage of Memory in your code - you have to go to memory tools, like Instruments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM