ROS cv_bridge::toCvCopy 因分段错误而失败
ROS cv_bridge::toCvCopy fails with segmentation fault
我遇到了一个奇怪的分段错误。在 ROS 节点中执行 cv_bridge::toCvCopy
时,它因分段错误而失败。我确定给定的消息有数据,代码用try...catch
.
括起来
ROS版本:kinetic,OpenCV版本:2.4,Ubuntu版本:16.04.
代码:
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
void ImageCallback(const sensor_msgs::ImageConstPtr& msg)
{
std::cerr<<"msg->header: "<<msg->header<<std::endl;
std::cerr<<"msg->height: "<<msg->height<<std::endl;
std::cerr<<"msg->width: "<<msg->width<<std::endl;
std::cerr<<"msg->encoding: "<<msg->encoding<<std::endl;
std::cerr<<"msg->is_bigendian: "<<int(msg->is_bigendian)<<std::endl;
std::cerr<<"msg->step: "<<msg->step<<std::endl;
std::cerr<<"msg->data.size(): "<<msg->data.size()<<std::endl;
std::cerr<<"msg->data[0,1,2]: "<<int(msg->data[0])<<" "<<int(msg->data[1])<<" "<<int(msg->data[2])<<std::endl;
std::cerr<<"msg->data[size()-1]: "<<int(msg->data[msg->data.size()-1])<<std::endl;
std::cerr<<"msg->data[size()-2]: "<<int(msg->data[msg->data.size()-2])<<std::endl;
std::cerr<<"msg->data[size()-3]: "<<int(msg->data[msg->data.size()-3])<<std::endl;
cv_bridge::CvImagePtr cv_ptr;
try
{
cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
std::cerr<<"debug.p1"<<std::endl;
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("cv_bridge exception: %s", e.what());
return;
}
std::cerr<<"cv_ptr: "<<cv_ptr<<std::endl;
std::cerr<<"cv_ptr->image: "<<cv_ptr->image<<std::endl;
cv::Mat frame= cv_ptr->image;
cv::imshow("camera",frame);
char c(cv::waitKey(1));
if(c=='\x1b'||c=='q') ros::shutdown();
}
int main(int argc, char**argv)
{
ros::init(argc, argv, "sub_img_node");
ros::NodeHandle node("~");
std::string img_topic("/camera/color/image_raw");
if(argc>1) img_topic= argv[1];
cv::namedWindow("camera",1);
ros::Subscriber sub_img= node.subscribe(img_topic, 1, &ImageCallback);
ros::spin();
return 0;
}
输出:
msg->header: seq: 352
stamp: 1610458354.727051013
frame_id: head_camera
msg->height: 480
msg->width: 640
msg->encoding: rgb8
msg->is_bigendian: 0
msg->step: 1920
msg->data.size(): 921600
msg->data[0,1,2]: 207 224 219
msg->data[size()-1]: 209
msg->data[size()-2]: 212
msg->data[size()-3]: 201
Segmentation fault (core dumped)
从结果可以看出,主题msg
的数据是正确的,cv_bridge::toCvCopy
后面的那一行没有被执行,所以段错误发生在cv_bridge::toCvCopy
。
此外,我用gdb分析了核心转储:
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
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-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 bin/sub_img_node...done.
[New LWP 101971]
[New LWP 101976]
[New LWP 101983]
[New LWP 101984]
[New LWP 101981]
[New LWP 101972]
[New LWP 101982]
[New LWP 101974]
[New LWP 101975]
warning: Unexpected size of section `.reg-xstate/101971' in core file.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `bin/sub_img_node /usb_cam/image_raw'.
Program terminated with signal SIGSEGV, Segmentation fault.
warning: Unexpected size of section `.reg-xstate/101971' in core file.
#0 0x00007fb2f5026b44 in cv::_InputArray::type(int) const () from /usr/lib/x86_64-linux-gnu/libopencv_core.so.2.4
[Current thread is 1 (Thread 0x7fb2f628fac0 (LWP 101971))]
(gdb) bt
#0 0x00007fb2f5026b44 in cv::_InputArray::type(int) const () from /usr/lib/x86_64-linux-gnu/libopencv_core.so.2.4
#1 0x00007fb2efa655bc in cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int) ()
from /opt/ros/kinetic/lib/x86_64-linux-gnu/libopencv_imgproc3.so.3.3
#2 0x00007fb2f5505cf3 in cv_bridge::toCvCopyImpl(cv::Mat const&, std_msgs::Header_<std::allocator<void> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
from /opt/ros/kinetic/lib/libcv_bridge.so
#3 0x00007fb2f5506103 in cv_bridge::toCvCopy(sensor_msgs::Image_<std::allocator<void> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /opt/ros/kinetic/lib/libcv_bridge.so
#4 0x00007fb2f55061e0 in cv_bridge::toCvCopy(boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /opt/ros/kinetic/lib/libcv_bridge.so
#5 0x00000000004074fb in ImageCallback (msg=...) at /home/akihikoy/prg/ay_test/ros/cpp_ros/test2/src/sub_img_node.cpp:49
#6 0x000000000040a91b in boost::function1<void, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&>::operator() (a0=...,
this=<optimized out>) at /usr/include/boost/function/function_template.hpp:773
#7 boost::detail::function::void_function_obj_invoker1<boost::function<void (boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&)>, void, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> >::invoke(boost::detail::function::function_buffer&, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const>) (function_obj_ptr=..., a0=...) at /usr/include/boost/function/function_template.hpp:159
#8 0x000000000040af63 in boost::function1<void, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> >::operator() (a0=..., this=<optimized out>)
at /usr/include/boost/function/function_template.hpp:773
#9 ros::SubscriptionCallbackHelperT<boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&, void>::call (this=0x12915e0, params=...)
at /opt/ros/kinetic/include/ros/subscription_callback_helper.h:144
#10 0x00007fb2f5ec2e2d in ros::SubscriptionQueue::call() () from /opt/ros/kinetic/lib/libroscpp.so
#11 0x00007fb2f5e686f8 in ros::CallbackQueue::callOneCB(ros::CallbackQueue::TLS*) () from /opt/ros/kinetic/lib/libroscpp.so
#12 0x00007fb2f5e6a0fb in ros::CallbackQueue::callAvailable(ros::WallDuration) () from /opt/ros/kinetic/lib/libroscpp.so
#13 0x00007fb2f5ec6ef9 in ros::SingleThreadedSpinner::spin(ros::CallbackQueue*) () from /opt/ros/kinetic/lib/libroscpp.so
#14 0x00007fb2f5eabedb in ros::spin() () from /opt/ros/kinetic/lib/libroscpp.so
#15 0x0000000000406276 in main (argc=2, argv=0x7ffe650933c8) at /home/akihikoy/prg/ay_test/ros/cpp_ros/test2/src/sub_img_node.cpp:78
但是我找不到错误的原因。谁能提出解决方案?
我不知道为什么,但我通过在 libcv-bridge0d
包中将 /opt/ros/kinetic/lib/libcv_bridge.so
替换为 libcv_bridge.so.0d
解决了这个问题。
详细流程:
$ sudo apt-get -f install libcv-bridge0d
$ cd /opt/ros/kinetic/lib/
$ sudo mv libcv_bridge.so{,.trouble}
$ sudo ln -s /usr/lib/x86_64-linux-gnu/libcv_bridge.so.0d libcv_bridge.so
我在Python也遇到了类似的问题,可以这样解决:
$ sudo apt-get -f install python-cv-bridge
我遇到了一个奇怪的分段错误。在 ROS 节点中执行 cv_bridge::toCvCopy
时,它因分段错误而失败。我确定给定的消息有数据,代码用try...catch
.
ROS版本:kinetic,OpenCV版本:2.4,Ubuntu版本:16.04.
代码:
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
void ImageCallback(const sensor_msgs::ImageConstPtr& msg)
{
std::cerr<<"msg->header: "<<msg->header<<std::endl;
std::cerr<<"msg->height: "<<msg->height<<std::endl;
std::cerr<<"msg->width: "<<msg->width<<std::endl;
std::cerr<<"msg->encoding: "<<msg->encoding<<std::endl;
std::cerr<<"msg->is_bigendian: "<<int(msg->is_bigendian)<<std::endl;
std::cerr<<"msg->step: "<<msg->step<<std::endl;
std::cerr<<"msg->data.size(): "<<msg->data.size()<<std::endl;
std::cerr<<"msg->data[0,1,2]: "<<int(msg->data[0])<<" "<<int(msg->data[1])<<" "<<int(msg->data[2])<<std::endl;
std::cerr<<"msg->data[size()-1]: "<<int(msg->data[msg->data.size()-1])<<std::endl;
std::cerr<<"msg->data[size()-2]: "<<int(msg->data[msg->data.size()-2])<<std::endl;
std::cerr<<"msg->data[size()-3]: "<<int(msg->data[msg->data.size()-3])<<std::endl;
cv_bridge::CvImagePtr cv_ptr;
try
{
cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
std::cerr<<"debug.p1"<<std::endl;
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("cv_bridge exception: %s", e.what());
return;
}
std::cerr<<"cv_ptr: "<<cv_ptr<<std::endl;
std::cerr<<"cv_ptr->image: "<<cv_ptr->image<<std::endl;
cv::Mat frame= cv_ptr->image;
cv::imshow("camera",frame);
char c(cv::waitKey(1));
if(c=='\x1b'||c=='q') ros::shutdown();
}
int main(int argc, char**argv)
{
ros::init(argc, argv, "sub_img_node");
ros::NodeHandle node("~");
std::string img_topic("/camera/color/image_raw");
if(argc>1) img_topic= argv[1];
cv::namedWindow("camera",1);
ros::Subscriber sub_img= node.subscribe(img_topic, 1, &ImageCallback);
ros::spin();
return 0;
}
输出:
msg->header: seq: 352
stamp: 1610458354.727051013
frame_id: head_camera
msg->height: 480
msg->width: 640
msg->encoding: rgb8
msg->is_bigendian: 0
msg->step: 1920
msg->data.size(): 921600
msg->data[0,1,2]: 207 224 219
msg->data[size()-1]: 209
msg->data[size()-2]: 212
msg->data[size()-3]: 201
Segmentation fault (core dumped)
从结果可以看出,主题msg
的数据是正确的,cv_bridge::toCvCopy
后面的那一行没有被执行,所以段错误发生在cv_bridge::toCvCopy
。
此外,我用gdb分析了核心转储:
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
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-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 bin/sub_img_node...done.
[New LWP 101971]
[New LWP 101976]
[New LWP 101983]
[New LWP 101984]
[New LWP 101981]
[New LWP 101972]
[New LWP 101982]
[New LWP 101974]
[New LWP 101975]
warning: Unexpected size of section `.reg-xstate/101971' in core file.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `bin/sub_img_node /usb_cam/image_raw'.
Program terminated with signal SIGSEGV, Segmentation fault.
warning: Unexpected size of section `.reg-xstate/101971' in core file.
#0 0x00007fb2f5026b44 in cv::_InputArray::type(int) const () from /usr/lib/x86_64-linux-gnu/libopencv_core.so.2.4
[Current thread is 1 (Thread 0x7fb2f628fac0 (LWP 101971))]
(gdb) bt
#0 0x00007fb2f5026b44 in cv::_InputArray::type(int) const () from /usr/lib/x86_64-linux-gnu/libopencv_core.so.2.4
#1 0x00007fb2efa655bc in cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int) ()
from /opt/ros/kinetic/lib/x86_64-linux-gnu/libopencv_imgproc3.so.3.3
#2 0x00007fb2f5505cf3 in cv_bridge::toCvCopyImpl(cv::Mat const&, std_msgs::Header_<std::allocator<void> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
from /opt/ros/kinetic/lib/libcv_bridge.so
#3 0x00007fb2f5506103 in cv_bridge::toCvCopy(sensor_msgs::Image_<std::allocator<void> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /opt/ros/kinetic/lib/libcv_bridge.so
#4 0x00007fb2f55061e0 in cv_bridge::toCvCopy(boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from /opt/ros/kinetic/lib/libcv_bridge.so
#5 0x00000000004074fb in ImageCallback (msg=...) at /home/akihikoy/prg/ay_test/ros/cpp_ros/test2/src/sub_img_node.cpp:49
#6 0x000000000040a91b in boost::function1<void, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&>::operator() (a0=...,
this=<optimized out>) at /usr/include/boost/function/function_template.hpp:773
#7 boost::detail::function::void_function_obj_invoker1<boost::function<void (boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&)>, void, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> >::invoke(boost::detail::function::function_buffer&, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const>) (function_obj_ptr=..., a0=...) at /usr/include/boost/function/function_template.hpp:159
#8 0x000000000040af63 in boost::function1<void, boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> >::operator() (a0=..., this=<optimized out>)
at /usr/include/boost/function/function_template.hpp:773
#9 ros::SubscriptionCallbackHelperT<boost::shared_ptr<sensor_msgs::Image_<std::allocator<void> > const> const&, void>::call (this=0x12915e0, params=...)
at /opt/ros/kinetic/include/ros/subscription_callback_helper.h:144
#10 0x00007fb2f5ec2e2d in ros::SubscriptionQueue::call() () from /opt/ros/kinetic/lib/libroscpp.so
#11 0x00007fb2f5e686f8 in ros::CallbackQueue::callOneCB(ros::CallbackQueue::TLS*) () from /opt/ros/kinetic/lib/libroscpp.so
#12 0x00007fb2f5e6a0fb in ros::CallbackQueue::callAvailable(ros::WallDuration) () from /opt/ros/kinetic/lib/libroscpp.so
#13 0x00007fb2f5ec6ef9 in ros::SingleThreadedSpinner::spin(ros::CallbackQueue*) () from /opt/ros/kinetic/lib/libroscpp.so
#14 0x00007fb2f5eabedb in ros::spin() () from /opt/ros/kinetic/lib/libroscpp.so
#15 0x0000000000406276 in main (argc=2, argv=0x7ffe650933c8) at /home/akihikoy/prg/ay_test/ros/cpp_ros/test2/src/sub_img_node.cpp:78
但是我找不到错误的原因。谁能提出解决方案?
我不知道为什么,但我通过在 libcv-bridge0d
包中将 /opt/ros/kinetic/lib/libcv_bridge.so
替换为 libcv_bridge.so.0d
解决了这个问题。
详细流程:
$ sudo apt-get -f install libcv-bridge0d
$ cd /opt/ros/kinetic/lib/
$ sudo mv libcv_bridge.so{,.trouble}
$ sudo ln -s /usr/lib/x86_64-linux-gnu/libcv_bridge.so.0d libcv_bridge.so
我在Python也遇到了类似的问题,可以这样解决:
$ sudo apt-get -f install python-cv-bridge