简单的 C++ OpenCV imshow 示例因分段错误而崩溃

Posted

技术标签:

【中文标题】简单的 C++ OpenCV imshow 示例因分段错误而崩溃【英文标题】:simple C++ OpenCV imshow example crashes with segmentation fault 【发布时间】:2016-12-20 11:08:32 【问题描述】:

(抱歉英语不好,我是德国人)

各位程序员

理论上,这个简单的 C++ OpenCV 示例应该显示一个 100x100 的黑色图像,等到按下某个键,将“仍在运行!\n”写入错误流并退出,退出代码为 123。

当我运行这个程序时,我看到黑色图像,直到我按下一个键。在我查看终端之前,似乎一切正常:

$ ./a.out
still running!
Segmentation fault (Core dumped) #shouldn't happen
$ echo $?
139       #should be 123
$

如果有人能回答我以下问题之一,我将不胜感激: - 为什么这个程序会产生分段错误? - 我怎样才能解决这个问题? - 源代码有问题吗?如果不是,哪个库/程序会导致此错误?

我可以听到你在尖叫:“但是,如果它只在调用 exit/return 时崩溃,那你为什么要关心?程序正常退出或崩溃都没有关系”。 你是对的,但我担心导致该程序在退出时崩溃的相同错误可能会导致程序在运行时崩溃/导致其他奇怪的问题。

#include <opencv2/opencv.hpp>
#include <iostream>
int main(void) 
    
        cv::Mat test(100, 100, CV_8UC1, cv::Scalar(0));
        //cv::namedWindow( "testName", cv::WINDOW_NORMAL ); //doesn't help
        //cv::namedWindow( "testName", cv::WINDOW_OPENGL ); //doesn't help
        cv::imshow( "testName", test );
        cv::waitKey(0);
        //cv::destroyAllWindows(); //doesn't help
    
    std::cerr << "still running!\n";
    return 123;

编译:

$ g++ `pkg-config --cflags --libs opencv` main.cpp

$ g++ -lopencv_core -lopencv_highgui main.cpp

关于我的电脑的一些附加信息:

操作系统:Linux (Fedora 25)

$ cat /proc/version

Linux 版本 4.8.14-300.fc25.x86_64 (mockbuild@bkernel02.phx2.fedoraproject.org) (gcc 版本 6.2.1 20160916 (Red Hat 6.2.1-2) (GCC)) #1 SMP Mon Dec 12 16:31:04 UTC 2016

使用以下命令安装 OpenCV:dnf install -y opencv*

输入 dnf remove opencv 并点击 tab 会产生以下输出:

opencv-3.1.0-8.fc25.x86_64             opencv-devel-3.1.0-8.fc25.x86_64
opencv-contrib-3.1.0-8.fc25.x86_64     opencv-devel-docs-3.1.0-8.fc25.noarch
opencv-core-3.1.0-8.fc25.x86_64        opencv-python-3.1.0-8.fc25.x86_64

更新:

$ valgrind ./a.out
==24083== Memcheck, a memory error detector
==24083== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==24083== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==24083== Command: ./a.out
==24083== 
^C==24083== 
==24083== Process terminating with default action of signal 2 (SIGINT)
==24083==    at 0x401B4B5: open (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4005547: open_verify.constprop.7 (in /usr/lib64/ld-2.24.so)
==24083==    by 0x40090BF: _dl_map_object (in /usr/lib64/ld-2.24.so)
==24083==    by 0x400DDFF: openaux (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4010873: _dl_catch_error (in /usr/lib64/ld-2.24.so)
==24083==    by 0x400E44D: _dl_map_object_deps (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4003146: dl_main (in /usr/lib64/ld-2.24.so)
==24083==    by 0x401991E: _dl_sysdep_start (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4004F67: _dl_start (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4000CD7: ??? (in /usr/lib64/ld-2.24.so)
==24083== Jump to the invalid address stated on the next line
==24083==    at 0x5A6: ???
==24083==    by 0x4005547: open_verify.constprop.7 (in /usr/lib64/ld-2.24.so)
==24083==    by 0x40090BF: _dl_map_object (in /usr/lib64/ld-2.24.so)
==24083==    by 0x400DDFF: openaux (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4010873: _dl_catch_error (in /usr/lib64/ld-2.24.so)
==24083==    by 0x400E44D: _dl_map_object_deps (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4003146: dl_main (in /usr/lib64/ld-2.24.so)
==24083==    by 0x401991E: _dl_sysdep_start (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4004F67: _dl_start (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4000CD7: ??? (in /usr/lib64/ld-2.24.so)
==24083==  Address 0x5a6 is not stack'd, malloc'd or (recently) free'd
==24083== 
==24083== 
==24083== Process terminating with default action of signal 11 (SIGSEGV)
==24083==  Bad permissions for mapped region at address 0x5A6
==24083==    at 0x5A6: ???
==24083==    by 0x4005547: open_verify.constprop.7 (in /usr/lib64/ld-2.24.so)
==24083==    by 0x40090BF: _dl_map_object (in /usr/lib64/ld-2.24.so)
==24083==    by 0x400DDFF: openaux (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4010873: _dl_catch_error (in /usr/lib64/ld-2.24.so)
==24083==    by 0x400E44D: _dl_map_object_deps (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4003146: dl_main (in /usr/lib64/ld-2.24.so)
==24083==    by 0x401991E: _dl_sysdep_start (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4004F67: _dl_start (in /usr/lib64/ld-2.24.so)
==24083==    by 0x4000CD7: ??? (in /usr/lib64/ld-2.24.so)
==24083== 
==24083== HEAP SUMMARY:
==24083==     in use at exit: 0 bytes in 0 blocks
==24083==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==24083== 
==24083== All heap blocks were freed -- no leaks are possible
==24083== 
==24083== For counts of detected and suppressed errors, rerun with: -v
==24083== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (Speicherabzug geschrieben)

更新 #2

$ g++ -g `pkg-config --cflags --libs opencv` main.cpp; gdb a.out
GNU gdb (GDB) Fedora 7.12-29.fc25
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...done.
(gdb) run
Starting program: /home/volker/Dropbox/Roboter/eclipse/CVS/source/a.out 
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.24-3.fc25.x86_64
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7fffc86e1700 (LWP 5063)]
[New Thread 0x7fffbd3b9700 (LWP 5072)]
[New Thread 0x7fffb5974700 (LWP 5089)]
[New Thread 0x7fffb5173700 (LWP 5090)]
[New Thread 0x7fffb4972700 (LWP 5091)]
[New Thread 0x7fffa796c700 (LWP 5100)]
still running!

Thread 7 "QDBusConnection" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffa796c700 (LWP 5100)]
0x00007fffefa5601d in QObject::disconnect(QObject const*, char const*, QObject const*, char const*) () from /lib64/libQt5Core.so.5
Missing separate debuginfos, use: dnf debuginfo-install LONG LIST OF PACKAGES
(gdb) backtrace
#0  0x00007fffefa5601d in QObject::disconnect(QObject const*, char const*, QObject const*, char const*) () from /lib64/libQt5Core.so.5
#1  0x00007fffbec6bfb0 in QDBusConnectionPrivate::closeConnection() () from /lib64/libQt5DBus.so.5
#2  0x00007fffbec58852 in QDBusConnectionManager::run() () from /lib64/libQt5DBus.so.5
#3  0x00007fffef88b9da in QThreadPrivate::start(void*) () from /lib64/libQt5Core.so.5
#4  0x00007ffff077e6ca in start_thread () from /lib64/libpthread.so.0
#5  0x00007ffff0a9cf6f in clone () from /lib64/libc.so.6
(gdb) 

【问题讨论】:

您可以使用 gdb 更具体地了解它是如何崩溃的吗? 我使用了 valgrind,但我很快就会使用 gdb 并在此处发布输出 无法在 Ubuntu 16.04.1 上重现它。它对我来说很好。看起来像一个配置错误的 DBus(不幸的是,我不知道如何修复它:-( ) 也许你没有链接到同一个 stdlib,因为 OpenCV 是针对的。 看起来像一个 Qt 错误,提到了here。你能尝试在没有 Qt 的情况下构建 OpenCV 吗? 【参考方案1】:

我使用"gdb""eclipse-cdt" 进行了调试。

    用“gdb”运行程序,用"dnf debuginfo-install".安装调试信息 监控"QApplicationPrivate :: app_style"的值和类型。 在“adwaitastyleplugin.cpp”的"StylePlugin :: ~ StylePlugin ()" 中设置断点。 在调用层次结构视图中查看“qlibrary.cpp: bool QLibraryPrivate :: unload (UnloadFlag flag)”。

我确认了

"QLibraryPrivate :: unload ()" will destroy "QApplicationPrivate :: app_style".
"QDBusConnectionPrivate :: closeConnection ()"

应该在"QLibraryPrivate :: unload ()"之前执行。

另外,我担心"adwaita :: style" 类的基类"QCommonStyle" 的析构函数不是"virtual"

我还在调查。

【讨论】:

我认为我可以解决这个问题。 1.安装软件“Qt Creator”。 2.添加包含目录“/usr/include/qt5”。 3. 添加库“Qt5Core”。 4. 添加编译选项“-fPIC”。 5. 添加源代码“#include ”。 6.调用源代码“if(qApp) delete qApp;”在 main 函数的末尾。 TODO: 1. 使用“int atexit(void (* function) (void))”。 2. 会不会发生内存泄漏? 3、“QCommonStyle”和“QCoreApplication”的析构函数不是“虚”的。 4.查看最新版Qt的源码。 (Qt 最新源代码测试) 1. 见 -> wiki.qt.io/Building_Qt_5_from_Git 2. cd $HOME 3. git clone github.com/qt/qtbase.git 4. cd qtbase 5. git pull 6. ./configure - developer-build -opensource -nomake examples -nomake tests 7. make -j4 8. export LD_LIBRARY_PATH=$HOME/qtbase/lib:$LD_LIBRARY_PATH 为什么无效? -> QT_PLUGIN_PATH 为什么无效? -> QT_QPA_FONTDIR 为什么无效? -> QT_QPA_PLATFORM_PLUGIN_PATH 9. 用 Valgrind 测试我的程序 -> Valgrind 检测到许多关于 Qt 的内存泄漏。 "export QT_QPA_FONTDIR = /usr/share/fonts/vlgothic" 有效。 Qt最新源代码每天更新,但有内存泄漏。 Qt 源代码需要打补丁。 'qasciikey.cpp' 中的函数 'Qt :: Key QTest :: asciiToKey (char ascii)' 调用宏 'QTEST_ASSERT (false)' 并引发 SIGABRT。 这个问题已经用opencv-3.4.1-3.fc-28-x86-64-rpm解决了,但是仍然存在以下问题: 1.即使按下窗口的关闭按钮,它不会从 cv::waitkey() 返回给调用者。我按 Ctrl-C 中止了程序。 2.窗口菜单操作后如果通过cv::waitkey(),会出现core dump的情况。

以上是关于简单的 C++ OpenCV imshow 示例因分段错误而崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Opencv C++为每个imshow打开两个窗口

OpenCV学习笔记——imreadimwrite以及imshow

Opencv:无法打开显示:C++、Raspberry Pi 无头连接

如何在 OSX 中使用 C++ opencv highgui 将活动窗口设置为 opencv 图像

Opencv视觉处理(C++)语法学习图像的算术与逻辑运算

OpenCV 不会流式传输/更新我的视频。如何更新 imshow 窗口? [复制]