Sto cercando di utilizzare RNCryptor per crittografare e decrittografare file di grandi dimensioni (600 + MB) su iOS. Su the github ho trovato codice di esempio su come utilizzare la libreria in modo asincrono sugli stream. Questo codice è simile alla risposta di Rob Napier su a question about this same subject.Problemi di memoria durante la crittografia/decrittografia di un file di grandi dimensioni con RNCryptor su iOS
Tuttavia, anche se penso di aver implementato correttamente il codice, l'app utilizza fino a 1,5 GB di memoria (nel simulatore di iPad 6.1). Pensavo che il codice avrebbe dovuto impedire all'app di mantenere più di un blocco di dati in memoria? Allora, cosa sta andando male?
Nel mio controller, creo un "CryptController" che messaggio con le richieste di crittografia/decrittografia.
// Controller.m
NSString *password = @"pw123";
self.cryptor = [[CryptController alloc] initWithPassword:password];
//start encrypting file
[self.cryptor streamEncryptRequest:self.fileName andExtension:@"pdf" withURL:[self samplesURL]];
//wait for encryption to finish
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:1];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:timeout];
} while (![self.cryptor isFinished]);
In CryptController ho:
- (void)streamEncryptionDidFinish {
if (self.cryptor.error) {
NSLog(@"An error occurred. You cannot trust decryptedData at this point");
}
else {
NSLog(@"%@ is complete. Use it as you like", [self.tempURL lastPathComponent]);
}
self.cryptor = nil;
self.isFinished = YES;
}
- (void) streamEncryptRequest:(NSString *)fileName andExtension:(NSString *)ext withURL:(NSURL *)directory {
//Make sure that this number is larger than the header + 1 block.
int blockSize = 32 * 1024;
NSString *encryptedFileName = [NSString stringWithFormat:@"streamEnc_%@", fileName];
self.tempURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
self.tempURL = [self.tempURL URLByAppendingPathComponent:encryptedFileName isDirectory:NO];
self.tempURL = [self.tempURL URLByAppendingPathExtension:@"crypt"];
NSInputStream *decryptedStream = [NSInputStream inputStreamWithURL:[[directory URLByAppendingPathComponent:fileName isDirectory:NO] URLByAppendingPathExtension:ext]];
NSOutputStream *cryptedStream = [NSOutputStream outputStreamWithURL:self.tempURL append:NO];
[cryptedStream open];
[decryptedStream open];
__block NSMutableData *data = [NSMutableData dataWithLength:blockSize];
__block RNEncryptor *encryptor = nil;
dispatch_block_t readStreamBlock = ^{
[data setLength:blockSize];
NSInteger bytesRead = [decryptedStream read:[data mutableBytes] maxLength:blockSize];
if (bytesRead < 0) {
//Throw an error
}
else if (bytesRead == 0) {
[encryptor finish];
}
else {
[data setLength:bytesRead];
[encryptor addData:data];
//NSLog(@"Sent %ld bytes to encryptor", (unsigned long)bytesRead);
}
};
encryptor = [[RNEncryptor alloc] initWithSettings:kRNCryptorAES256Settings
password:self.password
handler:^(RNCryptor *cryptor, NSData *data) {
//NSLog(@"Encryptor received %ld bytes", (unsigned long)data.length);
[cryptedStream write:data.bytes maxLength:data.length];
if (cryptor.isFinished) {
[decryptedStream close];
//call my delegate that i'm finished with decrypting
[self streamEncryptionDidFinish];
}
else {
readStreamBlock();
}
}];
// Read the first block to kick things off
self.isFinished = NO;
readStreamBlock();
}
Quando ho profilo utilizzando lo strumento di allocazione, le categorie di allocazione vedo costantemente in crescita sono malloc 32.50 KB
, malloc 4.00 KB
, NSConcreteData
e NSSubrangeData
. Soprattutto il malloc 32.50 KB
diventa grande, oltre 1 GB. Il chiamante responsabile è [NSConcreteData initWithBytes:length:copy:freeWhenDone:bytesAreVM:]
Per NSConcreteData
il chiamante responsabile è -[NSData(NSData) copyWithZone:]
.
Quando profilo utilizzando lo strumento Leaks, non vengono rilevate perdite.
Sono nuovo di Objective-C, e da quello che ho capito, il nuovo ARC dovrebbe gestire l'allocazione e la deallocazione della memoria. Quando si cerca su qualsiasi cosa relativa alla memoria, tutte le informazioni che trovo presuppongono che tu non usi ARC (o che non esistesse al momento della scrittura). Sono sicuro che sto usando ARC, dal momento che mi vengono compilati errori che lo dicono quando provo a deallocare manualmente la memoria.
Se qualcuno mi può aiutare con questo, sarebbe molto apprezzato! Se sono necessarie ulteriori informazioni, sarò felice di fornirlo :) Inoltre, sono nuovo di StackOverflow, quindi se c'è qualcosa che ho trascurato che avrei dovuto fare, gentilmente informami!
Ho appena provato la lettura e la scrittura di corsi d'acqua, solo per assicurarsi che il problema di memoria non è da qualche parte in là. La memoria non superava 1 MB, quindi il problema è con il codice di crittografia da qualche parte. – Johanneke