问题
I found the following code to get the local IP addresses using libboost. I am using 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();
}
I am currently getting an output of
daniel-XVirtualBox
127.0.1.1:0
free(): invalid size
Aborted (core dumped)
The hostname is correct, and the IP address of the localhost. I know that there are multiple interfaces on the computer and that query can return any number of them, but I do not see the two other interfaces connected to the computer. I will add the output of ifconfig also.
However, my question is concerning the "free(): invalid size" bit. GDB says this in addition:
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
Is there a clean-up procedure for boost::asio::io_service that I am missing? Should the resolver be stopped? And also, why do I not see all the interfaces on the computer?
Thanks!
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
回答1:
You have triggered a nasty case of undefined behavior (UD), which ultimately lead to a SIGABRT
in your program. In 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.
Technically, just about anything can happen with your code after your function returns. In most cases, nothing happens, everybody will be happy and therefore people mostly ignore warnings like no return statement in function returning non-void
.
Now here you see why this can be a very bad thing. If you set the return type to void
instead of std::string
or if you do return some string, the program doesn't crash anymore.
While gcc-generated code seems to produce a 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, despite UB.
This piece of code is a true sweetie pie of undefined behavior that can really mess up your application.
回答2:
In addition to @andreee answer, always compile your code with -Wall -Wextra -Werror
to detect such nasty bugs at compile time. There is no excuse for not using these flags.
In my makefiles I usually use bash expansion -W{all,extra,error}
.
来源:https://stackoverflow.com/questions/50833352/libboost-resolver-received-sigabrt