有个计算机专业的学妹问我:我这个zip文件密码破解运行起来为什么内存爆了?
阅读原文时间:2023年07月08日阅读:2

1.这篇博文的由来

2.跑下错误代码,找病根

先把学妹发给我的错误代码放上,能发现他为了提高速度加了多线程的代码,很聪明哦:

import zipfile
import itertools
from concurrent.futures import ThreadPoolExecutor

def extract(file, password):
    if not flag: return
    file.extractall(path='.', pwd=''.join(password).encode('utf-8'))

def result(f):
    exception = f.exception()
    if not exception:
        print('密码为:', f.pwd)
        global flag
        flag = False

if __name__ == '__main__':
    flag = True
    pool = ThreadPoolExecutor(100)
    nums = [str(i) for i in range(10)]
    chrs = [chr(i) for i in range(65, 91)]
    password_lst = itertools.permutations(nums + chrs, 6)
    zfile = zipfile.ZipFile("加密文件.zip", 'r')
    for pwd in password_lst:
        if not flag: break
        f = pool.submit(extract, zfile, pwd)
        f.pwd = pwd
        f.pool = pool
        f.add_done_callback(result)

用他的代码跑一下,乖乖隆地咚~跑一会儿内存就爆了。

那么原因是因为:ThreadPoolExecutor默认使用的是无界队列,尝试密码的速度跟不上生产密码的速度,会把生产任务无限添加到队列中,导致内存被占满。

展示下,内存直接飙到95: 

然后导致程序崩溃:

3.找到病根,对症下药

修改下源码,发现ThreadPoolExecutor内部使用的是无界队列,所以导致内存直接飙满,重写ThreadPoolExecutor类中的_work_queue属性,将无界队列改成有界队列,这样就不会出现内存爆满的问题,看代码:

import queue
from concurrent.futures import ThreadPoolExecutor

class BoundedThreadPoolExecutor(ThreadPoolExecutor):
    def __init__(self, max_workers=None, thread_name_prefix=''):
        super().__init__(max_workers, thread_name_prefix)
        self._work_queue = queue.Queue(self._max_workers * 2) # 设置队列大小

最后学妹按我给他的建议,完美的破解密码成功。

点击领取干货满满

感谢观看,关注我持续为您分享干货内容,你的收藏、评论、点赞就是对我最大的支持! 需要领取我之前学习资料的可以私信我,告诉我你具体需要的资料。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章