猫狗二分法遇到cannot identify image file <_io.BytesIO object at 0x000002A881819678>

这篇博客介绍了如何通过Python脚本检查图片文件夹中格式错误的图片,例如遇到无法打开的Cat的666.jpg,并提供了解决方案——直接删除错误图片。脚本使用PIL库来尝试打开图片,并转换为RGB模式,从而检测图片的正确性。

这个错误是数据集中有图片格式出错打不开,只需把它删除即可。但是如何找出错误图片的位置

import os
from PIL import Image
folder_path = ''  #写入你图片所在的文件夹,即包含该图片的文件夹
extensions = []
for filee in os.listdir(folder_path):
    file_path = os.path.join(folder_path,
malloc(): invalid next->prev_inuse (unsorted) Thread 26 "stitch_sys.out" received signal SIGABRT, Aborted. [Switching to Thread 0x7fb61cd960 (LWP 7583)] __pthread_kill_implementation (threadid=548516190560, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44 44 ./nptl/pthread_kill.c: No such file or directory. (gdb) bt #0 __pthread_kill_implementation (threadid=548516190560, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44 #1 0x0000007ff6cef254 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78 #2 0x0000007ff6caa67c in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #3 0x0000007ff6c97130 in __GI_abort () at ./stdlib/abort.c:79 #4 0x0000007ff6ce3308 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ff6dc43b8 "%s\n") at ../sysdeps/posix/libc_fatal.c:155 #5 0x0000007ff6cf957c in malloc_printerr (str=str@entry=0x7ff6dbfcc0 "malloc(): invalid next->prev_inuse (unsorted)") at ./malloc/malloc.c:5664 #6 0x0000007ff6cfca84 in _int_malloc (av=av@entry=0x7fac000030, bytes=bytes@entry=11059272) at ./malloc/malloc.c:4012 #7 0x0000007ff6cfd6dc in __GI___libc_malloc (bytes=11059272) at ./malloc/malloc.c:3329 #8 0x0000007ff7b27618 in cv::fastMalloc(unsigned long) () from /usr/lib/opencv4.5.4/libopencv_core.so.4.5 #9 0x0000007ff7c2b78c in cv::Mat::create(int, int const*, int) () from /usr/lib/opencv4.5.4/libopencv_core.so.4.5 #10 0x0000007ff7c2bb3c in cv::Mat::create(int, int, int) () from /usr/lib/opencv4.5.4/libopencv_core.so.4.5 #11 0x0000007ff7b8efcc in cv::Mat::copyTo(cv::_OutputArray const&) const () from /usr/lib/opencv4.5.4/libopencv_core.so.4.5 #12 0x0000007ff7c2b2a8 in cv::Mat::clone() const () from /usr/lib/opencv4.5.4/libopencv_core.so.4.5
最新发布
09-16
<think> 嗯,用户现在遇到了一个"C语言的运行时错误",具体是'malloc(): invalid next->prev_inuse (unsorted)',而且出现在使用OpenCV 4.5.4库的程序'stitch_sys.out'中,还伴随着SIGABRT信号。这看起来像是内存管理出了严重问题。 让我分析一下这个错误信息。这个错误是glibc的内存分配器报出来的,通常意味着堆内存结构被破坏了。简单来说,就是程序在释放内存时,发现相邻的内存块状态不一致——当前块被标记为"使用中",但下一个块的"前一块在使用中"标志位却被错误设置。这种问题往往源于内存越界写入、重复释放、使用已释放内存等操作。 用户特别提到错误发生在使用OpenCV时,这让我想到几种可能性:可能是用户程序本身有内存错误,但只在调用OpenCV时才暴露;也可能是OpenCV库内部的问题;还有可能是程序与OpenCV的交互方式有问题。考虑到用户程序名为'stitch_sys.out',我猜测是在做图像拼接之类的处理,这类任务通常涉及大量内存操作。 从用户给出的引用内容看,里面提到了一些OpenCV数据结构如CvSeq,但这似乎只是背景资料,并非问题的直接线索。用户上次询问的是快速排序,与当前问题无关,所以应该专注于当前的内存错误。 解决这类问题确实比较棘手,因为错误发生点往往不是问题根源所在。我想到几个关键排查方向:首先要用Valgrind检查内存错误,这是最有效的工具;其次要检查所有涉及内存操作的代码,特别是数组和指针操作;还要注意OpenCV对象生命周期管理;最后考虑库版本问题或编译参数。 用户可能已经尝试过简单重启等方法无效,才会来寻求帮助。这类问题通常需要系统性的调试,我会建议从最基础的Valgrind检查开始,然后逐步深入到代码审查。如果用户是在做图像拼接,特别要注意拼接过程中创建的临时对象是否正确释放,以及是否在多个线程中不当共享了cv::Mat等对象。 考虑到用户的技术水平(能使用OpenCV做拼接系统),应该具备一定的调试能力,所以可以提供具体的工具使用命令和重点检查方向。不过也要提醒用户,这类问题可能需要耐心和时间来排查。 </think> 这个 `malloc(): invalid next->prev_inuse (unsorted)` 错误伴随 `SIGABRT` 信号,表明你的程序 (`stitch_sys.out`) 在内存管理上发生了严重问题,导致 C 标准库的内存分配器 (`malloc/free/realloc`) 检测到了堆内存结构被破坏。在使用 OpenCV 时遇到此问题,通常指向以下几种原因: **核心原因:内存越界访问或非法内存操作** 1. **内存越界写入:** * **最常见原因。** 你的代码(或 OpenCV 内部代码,但这个版本相对稳定,更可能是你的代码)向动态分配的内存块(如 `cv::Mat` 底层数据数组、字符串、自定义结构体数组)的 *尾部之后* 或 *头部之前* 写了数据。 * 例如: * 访问 `vector[idx]` 或 `mat.ptr<type>(row)[col]` 时 `idx`、`row`、`col` 超出了有效范围。 * 使用指针进行迭代时步进过大,超出了分配的内存块。 * 错误计算了需要复制的数据大小(如 `memcpy`, `std::copy` 的参数)。 2. **使用已释放内存:** * 在某个对象(如 `cv::Mat`, `cv::Ptr<>` 管理的对象、`std::vector` 等)已经被销毁或释放后,仍然尝试读取或写入其指向的内存区域。 3. **重复释放内存:** * 尝试多次释放同一块动态分配的内存。 * 手动 `delete` 或 `free` 了由 OpenCV 对象(如 `cv::Mat`)自动管理的内存(通常不应该这么做)。或者在对象已被智能指针释放后手动干预。 4. **指针操作错误:** * 使用了未初始化或已失效的野指针 (`wild pointer`)。 * 指针运算错误导致指向了非法地址。 * 错误的类型转换导致后续内存操作出错。 5. **栈溢出:** * 虽然不是直接的堆破坏,但栈溢出也可能导致内存布局混乱,间接触发类似错误。这通常发生在递归深度过大或在栈上分配巨大数组时。然而,`SIGABRT` 和这个特定错误信息更典型指向堆问题。 **为什么在使用 OpenCV (`stitch`) 时出现?** * `stitch` 通常涉及加载大图像、创建中间处理结果(如特征点、描述符、变换矩阵、融合图等),这些都是内存密集型操作,会频繁分配和释放大量内存。 * OpenCV 函数调用链很深。一个在你的代码中造成的细微内存损坏,可能在某个 OpenCV 内部函数(如内存分配器 `malloc`)试图使用这块损坏的内存结构时才被检测到并引发崩溃(`SIGABRT`),此时调用栈显示在 OpenCV 内部。但这并不意味着 OpenCV 库本身一定有 Bug(尤其是 4.5.4 是一个稳定版本),更可能是你的程序传入或使用了损坏的数据。 **解决方法与调试步骤:** 1. **使用内存调试工具(最重要!):** * **Valgrind (Linux/macOS):** ```bash valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=valgrind.log ./stitch_sys.out <your_arguments> ``` * 仔细分析 `valgrind.log` 文件。它会精准指出第一次内存非法操作的源头(越界读/写、使用已释放内存、未初始化访问等),通常能直接定位到代码行。 * **AddressSanitizer (ASan) (GCC/Clang/Linux/macOS/Windows/MSVC 较新版本):** * 在编译你的程序时添加 `-fsanitize=address -g` 标志(确保生成调试符号 `-g`)。 * 重新编译 OpenCV(可选但推荐,尤其如果怀疑是 OpenCV 内部问题): ```bash cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fsanitize=address" -DCMAKE_C_FLAGS="-fsanitize=address" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address" ... # 其他你的 OpenCV 配置参数 make -j8 ``` * 然后运行你的程序 (`stitch_sys.out`)。ASan 会在检测到内存错误时立即中止程序,并在终端打印详细的错误报告,包括调用栈和错误类型(越界访问、使用后释放、重复释放等),精确到代码行。比 Valgrind 更快但运行时开销稍大。 * **Dr. Memory (Windows):** 类似 Valgrind 的 Windows 替代品。 2. **仔细检查代码:** * **数组/容器边界:** 严格检查所有数组索引 (`[]`)、迭代器、指针运算。特别注意循环条件 (`<` vs `<=`)、动态分配大小后的访问。 * **OpenCV 对象生命周期:** * 确保 `cv::Mat`, `std::vector<cv::KeyPoint>`, `std::vector<cv::DMatch>` 等对象在需要使用时依然有效。 * 避免手动管理 `cv::Mat.data` 指针的生命周期。`cv::Mat` 有自己的引用计数机制,除非非常清楚后果且用 `Mat::release()` 或创建 `Mat` 时指定 `userdata`,否则不要 `delete` `data`。 * 理解 `cv::Ptr<>` 智能指针的行为,避免手动 `delete` 它管理的对象。 * **字符串操作:** 确保 `C` 风格字符串以 `\0` 结尾,使用 `strncpy` 避免溢出,注意 `sprintf`/`vsprintf` 的缓冲区大小(考虑 `snprintf`)。 * **自定义内存管理:** 如果代码中有 `new`/`delete` 或 `malloc`/`free`,务必成对使用,并确保指针有效。 * **多线程同步(如果使用多线程):** 内存损坏可能由多线程竞争访问同一内存区域引起。确保共享数据访问有适当的锁(`std::mutex` 等)保护。 3. **缩小问题范围:** * 尝试使用更小的输入图像或数据集运行程序,看错误是否消失或更容易在调试工具中定位。 * 注释掉部分代码逻辑,特别是非核心的图像处理步骤,逐步缩小触发问题的代码块。二分法排除很有效。 * 检查问题是否只在特定输入图像或特定操作(如拼接大量图像)后出现。 4. **检查 OpenCV 使用方式:** * **查阅文档:** 确认你使用的 OpenCV 函数 API 正确无误,参数传递正确(尤其是涉及图像尺寸、ROI 的区域)。 * **数据类型匹配:** 确保传递给 OpenCV 函数的数据类型(如 `CV_8UC3`, `CV_32F`)与实际数据一致。 * **内存连续性:** 注意 `cv::Mat::isContinuous()`。某些 OpenCV 函数要求输入是连续内存。使用 `mat.clone()` 或 `mat.copyTo()` 可以强制创建连续副本。 5. **环境与版本:** * **确保一致性:** 确认你的程序链接的 OpenCV 库版本确实是 4.5.4,并且编译环境和运行环境一致(尤其是库路径)。 * **更新库(次要尝试):** 虽然 4.5.4 稳定,但如果怀疑是特定 OpenCV 版本的罕见 Bug(可能性相对较低),可以尝试更新到 OpenCV 4.x 的最新版本(如 4.9.0)并重新编译你的程序测试。但**优先使用调试工具定位问题根源**。 **总结:** 解决 `malloc(): invalid next->prev_inuse (unsorted)` 和 `SIGABRT` 的关键在于 **精确找到内存破坏的点**。**Valgrind 或 AddressSanitizer (ASan) 是最强大、最有效的工具,务必优先使用它们进行诊断。** 结合仔细的代码审查(重点关注内存操作和 OpenCV 对象生命周期),通常能够定位并修复问题。这个问题几乎总是由应用程序代码(你的代码)中的 Bug 引起,而不是 OpenCV 库本身的根本原因(尽管错误可能在库代码中爆发)。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值