running out of memory from for loop

2019-07-19 03:22发布

Hey so i thought it would be cool if i made a little app that generated a random password and then had the app run through all the possibilities and try to see what the password was tell me how many times it attempted it. Sometime the app works sometimes it crashes depends on what the password is. I wanted to know f there was anything i could do to stop it from crashing by using up to much memory. This is the method.

-(void)hackString 
 {
    NSString *string;
    NSString *string1;
    NSString *string2;
    NSString *string3;
    NSString *string4;
    NSString *string5;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void){


    NSString *hackedString;

    for (string in self.validLetters) {
    //[hackedString appendString:string];
        for (string1 in self.validLetters) {
            //[hackedString appendString:string1];
            for (string2 in self.validLetters) {
                //[hackedString appendString:string1];
                for (string3 in self.validLetters) {
                    //[hackedString appendString:string1];
                    for (string4 in self.validLetters) {
                        for (string5 in self.validLetters) {
                             hackedString = [NSString stringWithFormat:@"%@%@%@%@%@%@",string,string1,string2,string3,string4,string5];
                           // NSLog(@"%@",hackedString);
                            [self testStringWithPassword:hackedString];

                        }

                    }
                }
            }
        }
    }
         });

} 

Is there anything I should be doing there to stop it from crashing?

3条回答
女痞
2楼-- · 2019-07-19 03:44

stringWithFormat: returns an autoreleased string. That means it doesn't get cleaned up until that method call returns (and the autorelease pool drains), so you run out of memory. If you're not using ARC, you can explicitly init and release the strings:

hackedString = [[NSString alloc] initWithFormat:@"%@%@%@%@%@%@",string,string1,string2,string3,string4,string5]];
[self testStringWithPassword:hackedString];
[hackedString release];

If you are using ARC, add an @autoreleasepool around one of the inner loops, I'd suggest the string4 loop.

查看更多
走好不送
3楼-- · 2019-07-19 03:48

If your app is running out of memory, it is most likely because your are filling the autorelease pool with tons of objects to the point of memory exhaustion.

Naively, you could use an @autoreleasepool{} around one of the inner for() loops.

However, most password entry systems immediately hash the password into some un-reverse-hashable string that is then compared with a stored hash. Thus, it is unlikely that your approach would be useful for testing passwords. You would likely need to implement the same hashing.

I used to run a password cracker (kinda like John the Ripper) on my company's user's password database, sending automatic emails to anyone whose password was weak. We ended up firing one person because they were incapable of thinking of a password that couldn't be defeated by the cracker within minutes (there were other reasons, similar in nature).

查看更多
贪生不怕死
4楼-- · 2019-07-19 03:52

Is there anything I should be doing there to stop it from crashing?

Are you sure the program is crashing? If your program is really crashing, you should be getting a crash log or console message that tells you where it crashed, and you should be able to see the place where it crashed in the debugger.

It may be that your program is simply taking a very long time to run because you're asking it to generate every combination of six strings from validLetters. Depending on the circumstances, it's also possible that your program is being killed by a watchdog process in the operating system.

On the other hand, your program really might be crashing because it's running out of memory. You're allocating memory every time you call -stringWithFormat:, which creates a new autoreleased string. Since you're never letting the run loop run, the autorelease pool never gets drained. If your program takes too long to find the string that it's looking for, you could easily be using up all your available memory. So, to start off, try putting your innermost for loop inside an @autorelease block, like:

@autorelease {
    for (string5 in self.validLetters) {
        hackedString = [NSString     stringWithFormat:@"%@%@%@%@%@%@",string,string1,string2,string3,string4,string5];
                           // NSLog(@"%@",hackedString);
        [self testStringWithPassword:hackedString];

    }
}
查看更多
登录 后发表回答