如何通过C++代码获取虚拟机的IPv6地址?
获取虚拟机IPv6地址的正确C++实现
首先,你的代码出现段错误(SIGSEGV)的核心原因是未检查getaddrinfo的返回值:当函数调用失败时res仍为NULL,直接访问res->ai_canonname会触发非法内存访问。此外,原参数设置也未精准匹配获取本机IPv6地址的需求,以下是完整修正方案:
关键修改点
- 强制检查
getaddrinfo及相关系统调用的返回值,避免空指针访问 - 将
hint.ai_family设为AF_INET6,限定仅返回IPv6类型地址 - 使用
getnameinfo(或inet_ntop)将二进制IPv6地址转换为可读字符串 - 遍历地址链表,处理所有可能的本机IPv6地址
- 调用
freeaddrinfo释放资源,避免内存泄漏
修正后的代码
#include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <cstring> #include <unistd.h> using namespace std; int main() { addrinfo hint, *res = nullptr, *p = nullptr; int err; char host[NI_MAXHOST]; // 初始化hint结构体,清空内存后设置参数 memset(&hint, 0, sizeof(hint)); hint.ai_family = AF_INET6; // 限定仅获取IPv6地址 hint.ai_socktype = SOCK_STREAM; // 指定TCP流类型(不影响地址获取) hint.ai_flags = AI_ADDRCONFIG; // 仅返回当前系统已配置的有效地址 // 获取本机主机名,用于解析本机地址 char hostname[256]; if (gethostname(hostname, sizeof(hostname)) != 0) { cerr << "获取主机名失败" << endl; return 1; } // 调用getaddrinfo获取地址信息链表 err = getaddrinfo(hostname, "http", &hint, &res); if (err != 0) { cerr << "getaddrinfo错误: " << gai_strerror(err) << endl; return 1; } // 遍历地址链表,输出所有IPv6地址 for (p = res; p != nullptr; p = p->ai_next) { err = getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof(host), nullptr, 0, NI_NUMERICHOST); if (err != 0) { cerr << "getnameinfo错误: " << gai_strerror(err) << endl; continue; } cout << "本机IPv6地址: " << host << endl; } // 释放getaddrinfo分配的内存资源 freeaddrinfo(res); return 0; }
代码说明
- 主机名获取:通过
gethostname获取本机主机名,确保getaddrinfo能精准解析本机的网络地址 - 地址族限定:
AF_INET6参数过滤掉IPv4地址,只保留IPv6类型的结果 - 错误处理:对所有系统调用的返回值做校验,提前拦截错误并输出提示
- 地址转换:
getnameinfo将二进制的sockaddr_in6结构体转换为人类可读的IPv6字符串,兼容性优于inet_ntop - 资源管理:
freeaddrinfo必须调用,否则会造成堆内存泄漏
内容的提问来源于stack exchange,提问作者mouse_00
相关产品推荐
相关产品推荐

