不能直接读整个大文件进内存算SHA256,因易OOM;应分块(如64KB)用EVP_DigestUpdate增量计算,注意二进制模式、gcount()判末块、EVP_DigestFinal_ex收尾及显式EVP_MD_CTX_free。为什么不能直接读整个大文件进内存算 SHA256因为会 OOM——哪怕只是 4GB 的文件,在 32 位环境或内存受限容器里,std::ifstream::read 一次性读取就可能失败;64 位下虽不崩,但占满几百 MB 内存毫无必要,还拖慢其他 IO。SHA256 本身支持增量更新(EVP_DigestUpdate 或 std::hasher::update),分块才是正解。常见错误现象:std::bad_alloc、程序卡死、校验结果和 sha256sum 不一致(通常是因为没处理末尾不足块的边界)。块大小建议选 65536(64KB):太小(如 1KB)系统调用开销大;太大(如 1MB)对缓存不友好,且在低内存设备上仍可能出问题必须用二进制模式打开文件:std::ios::binary,否则 Windows 下换行符会被悄悄转换,哈希值必然错每次 read() 后要检查 gcount(),不能只看 eof()——文件末尾读不满一块时,gcount() 才是真实字节数OpenSSL 的 EVP 接口怎么安全分块更新别碰 SHA256_Init/SHA256_Update 这类底层 C 接口,它们不校验指针/长度,容易传错参数导致段错误或哈希错。用 EVP_MD_CTX + EVP_DigestInit_ex 是 OpenSSL 官方推荐路径,支持多线程安全重用上下文。实操要点:立即学习“C++免费学习笔记(深入)”;初始化必须指定算法和 engine:EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr),漏掉 nullptr 可能触发未定义行为EVP_DigestUpdate 第二个参数是 const void*,传 buffer.data() 没问题,但确保 buffer 生命周期覆盖整个 update 过程最后一定要调 EVP_DigestFinal_ex,不能只靠 EVP_DigestUpdate——否则摘要没完成,输出全是 0错误检查不能省:EVP_DigestInit_ex 和 EVP_DigestFinal_ex 返回 1 才成功,否则查 ERR_print_errors_fp(stderr)用 std::filesystem::file_size 避免重复 stat有人边读边调 std::filesystem::file_size(path),其实没必要——它本质就是一次 stat() 系统调用。在校验前调一次就够了,还能提前判断文件是否为空或权限不足。 Cleanup.pictures 智能移除图片中的物体、文本、污迹、人物或任何不想要的东西

更多推荐