Libboost :: 解析器收到 SIGABRT
Libboost :: resolver received SIGABRT
我找到了以下使用 libboost 获取本地 IP 地址的代码。我正在使用 libboost-1.65。
#include <iostream>
#include <boost/asio.hpp>
std::string getHostIP ()
{
using boost::asio::ip::tcp;
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
std::cout << boost::asio::ip::host_name() << std::endl;
tcp::resolver::query query(boost::asio::ip::host_name(), "");
tcp::resolver::iterator iter = resolver.resolve(query);
tcp::resolver::iterator end; // End marker.
while (iter != end)
{
tcp::endpoint ep = *iter++;
std::cout << ep << std::endl;
}
}
int main() {
getHostIP();
}
我目前得到
的输出
daniel-XVirtualBox
127.0.1.1:0
free(): invalid size
Aborted (core dumped)
主机名正确,本地主机的IP地址。我知道计算机上有多个接口,查询可以 return 任意数量,但我没有看到连接到计算机的另外两个接口。我还将添加 ifconfig 的输出。
但是,我的问题是关于 "free(): invalid size" 位的。
GDB 补充说:
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
***Backtrace***
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff705a801 in __GI_abort () at abort.c:79
#2 0x00007ffff70a3897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff71d0b9a "%s\n")
at ../sysdeps/posix/libc_fatal.c:181
#3 0x00007ffff70aa90a in malloc_printerr (str=str@entry=0x7ffff71ceda0 "free(): invalid size") at malloc.c:5350
#4 0x00007ffff70b1e2c in _int_free (have_lock=0, p=0x7ffff7de5990 <_dl_init+864>, av=0x7ffff7405c40 <main_arena>)
at malloc.c:4161
#5 __GI___libc_free (mem=0x7ffff7de59a0 <_dl_fini>) at malloc.c:3124
#6 0x0000555555559111 in main () at boost_gethostname.cpp:22
是否有我缺少的 boost::asio::io_service 的清理程序?应该停止解析器吗?还有,为什么我在电脑上看不到所有接口?
谢谢!
ifconfig:
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255
inet6 fe80::ecd6:f288:3b03:d8cf prefixlen 64 scopeid 0x20<link>
ether 08:00:27:37:63:98 txqueuelen 1000 (Ethernet)
RX packets 114124 bytes 111705475 (111.7 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 42644 bytes 3732986 (3.7 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.11.221 netmask 255.255.255.0 broadcast 10.10.11.255
inet6 fe80::3aa2:ecbd:5702:2ab4 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:a6:44:ce txqueuelen 1000 (Ethernet)
RX packets 194194 bytes 24826176 (24.8 MB)
RX errors 0 dropped 7354 overruns 0 frame 0
TX packets 1189 bytes 127853 (127.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 912 bytes 76283 (76.2 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 912 bytes 76283 (76.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
您触发了一个严重的未定义行为 (UD) 案例,最终导致您的程序出现 SIGABRT
。在 9.6.3 [stmt.return]:
Flowing off the end of a constructor, a destructor, or a function with a cv void return type is equivalent to a return with no operand.
Otherwise, flowing off the end of a function other than main results in undefined behavior.
从技术上讲,几乎 任何事情 都可能在您的代码 return 之后发生。在大多数情况下,什么都不会发生,每个人都会很高兴,因此人们大多会忽略像 no return statement in function returning non-void
.
这样的警告
现在你明白为什么这会是一件非常的坏事了。如果您将 return 类型设置为 void
而不是 std::string
或者如果您 do return 一些字符串,程序不会崩溃了。
虽然 gcc 生成的代码似乎生成 segfault or an abort (depending on the version), clang-generated code will issue an illegal instruction. Both compilers do fine if you change the return type. For even more confusion, take gcc 4.9.x; here your code just works fine,尽管 UB。
这段代码是 undefined 行为的真正甜心,它会真正搞乱您的应用程序。
除了@andreee 的回答之外,总是 使用-Wall -Wextra -Werror
编译您的代码以在编译时检测此类讨厌的错误。没有理由不使用这些标志。
在我的 makefile 中,我通常使用 bash 扩展 -W{all,extra,error}
。
我找到了以下使用 libboost 获取本地 IP 地址的代码。我正在使用 libboost-1.65。
#include <iostream>
#include <boost/asio.hpp>
std::string getHostIP ()
{
using boost::asio::ip::tcp;
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
std::cout << boost::asio::ip::host_name() << std::endl;
tcp::resolver::query query(boost::asio::ip::host_name(), "");
tcp::resolver::iterator iter = resolver.resolve(query);
tcp::resolver::iterator end; // End marker.
while (iter != end)
{
tcp::endpoint ep = *iter++;
std::cout << ep << std::endl;
}
}
int main() {
getHostIP();
}
我目前得到
的输出daniel-XVirtualBox
127.0.1.1:0
free(): invalid size
Aborted (core dumped)
主机名正确,本地主机的IP地址。我知道计算机上有多个接口,查询可以 return 任意数量,但我没有看到连接到计算机的另外两个接口。我还将添加 ifconfig 的输出。
但是,我的问题是关于 "free(): invalid size" 位的。 GDB 补充说:
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
***Backtrace***
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff705a801 in __GI_abort () at abort.c:79
#2 0x00007ffff70a3897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff71d0b9a "%s\n")
at ../sysdeps/posix/libc_fatal.c:181
#3 0x00007ffff70aa90a in malloc_printerr (str=str@entry=0x7ffff71ceda0 "free(): invalid size") at malloc.c:5350
#4 0x00007ffff70b1e2c in _int_free (have_lock=0, p=0x7ffff7de5990 <_dl_init+864>, av=0x7ffff7405c40 <main_arena>)
at malloc.c:4161
#5 __GI___libc_free (mem=0x7ffff7de59a0 <_dl_fini>) at malloc.c:3124
#6 0x0000555555559111 in main () at boost_gethostname.cpp:22
是否有我缺少的 boost::asio::io_service 的清理程序?应该停止解析器吗?还有,为什么我在电脑上看不到所有接口?
谢谢!
ifconfig:
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255
inet6 fe80::ecd6:f288:3b03:d8cf prefixlen 64 scopeid 0x20<link>
ether 08:00:27:37:63:98 txqueuelen 1000 (Ethernet)
RX packets 114124 bytes 111705475 (111.7 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 42644 bytes 3732986 (3.7 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.11.221 netmask 255.255.255.0 broadcast 10.10.11.255
inet6 fe80::3aa2:ecbd:5702:2ab4 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:a6:44:ce txqueuelen 1000 (Ethernet)
RX packets 194194 bytes 24826176 (24.8 MB)
RX errors 0 dropped 7354 overruns 0 frame 0
TX packets 1189 bytes 127853 (127.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 912 bytes 76283 (76.2 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 912 bytes 76283 (76.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
您触发了一个严重的未定义行为 (UD) 案例,最终导致您的程序出现 SIGABRT
。在 9.6.3 [stmt.return]:
Flowing off the end of a constructor, a destructor, or a function with a cv void return type is equivalent to a return with no operand. Otherwise, flowing off the end of a function other than main results in undefined behavior.
从技术上讲,几乎 任何事情 都可能在您的代码 return 之后发生。在大多数情况下,什么都不会发生,每个人都会很高兴,因此人们大多会忽略像 no return statement in function returning non-void
.
现在你明白为什么这会是一件非常的坏事了。如果您将 return 类型设置为 void
而不是 std::string
或者如果您 do return 一些字符串,程序不会崩溃了。
虽然 gcc 生成的代码似乎生成 segfault or an abort (depending on the version), clang-generated code will issue an illegal instruction. Both compilers do fine if you change the return type. For even more confusion, take gcc 4.9.x; here your code just works fine,尽管 UB。
这段代码是 undefined 行为的真正甜心,它会真正搞乱您的应用程序。
除了@andreee 的回答之外,总是 使用-Wall -Wextra -Werror
编译您的代码以在编译时检测此类讨厌的错误。没有理由不使用这些标志。
在我的 makefile 中,我通常使用 bash 扩展 -W{all,extra,error}
。