今早在调试我64的sdk时发现,如果形参sz=16的时候(默认值),但是在构造函数中对数据成员进行赋值出现 count=0; size=sz; 结果却是cout=16,size =0特别奇怪;
代码如图:
GpSocketDef.h文件
//
//
class ParamHostAddr
{
public:
struct tagADDR
{
INT32 type;
char ip[GP_MAX_IP];
char mac[INTER_MAX_MAC];
};
ParamHostAddr(INT32 sz = 16)
{
addrs = NULL;
count = 0;
size = sz;
memset(hostname, 0, sizeof(hostname));
addrs = (tagADDR*)malloc(sizeof(tagADDR) * size);
memset(addrs, 0, sizeof(tagADDR) * size);
}
...
char hostname[MAX_PATH];
tagADDR* addrs;
INT32 count;
INT32 size;
};
GpSysNetwork.h头文件
进行前置声明和在GpSysNetwork.cpp中进行调用
GpSysNetwork.cpp文件
//
//
INT32 getHostAddrInfo(ParamHostAddr& addr)
{
#if defined(WIN32) || defined(WIN64)
//*** 初始化网络库,否则gethostname获取失败10093错误
if (!g_bWSAStartup)
{
if (ReturnCode_Error == loadNetModule())
{
return ERR_SOCK_ERROR;
}
}
INT32 ret = gethostname(addr.hostname, sizeof(addr.hostname));
if (SOCKET_ERROR == ret)
{
// windows和linux系统获取错误码的接口有差异
INT32 err = getLaseError();
return ERR_SOCK_ERROR;
}
//printf("host name is %s \n", addr.hostname);
addrinfo hints, * results = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
ret = ::getaddrinfo(addr.hostname, NULL, &hints, &results);
if (NULL == results)
{
return ERR_SOCK_ERROR;
}
if (ret != 0)
{
//m_nErrorCode = ret;
//OnError(ret);
freeaddrinfo(results);
return ERR_SOCK_ERROR;
}
for (addrinfo* ptr = results; ptr != NULL && addr.idle(); ptr = ptr->ai_next)
{
sockaddr_in* pin = (sockaddr_in*)ptr->ai_addr;
addr.addr().type = pin->sin_family;
strcpy(addr.addr().ip, inet_ntoa(pin->sin_addr));
addr.add();
}
//freeaddrinfo
freeaddrinfo(results);
#elif defined(__linux__)
// linux系统getaddrinfo获取所有ip的功能异常,改用getifaddrs
ifaddrs *ifaddr,*ifaddrHeader;
if (getifaddrs(&ifaddr) != 0)
{
perror("getifaddrs :");
return ERR_SOCK_ERROR;
}
ifaddrHeader = ifaddr;
for (; ifaddr != NULL; ifaddr = (*ifaddr).ifa_next)
{
if ((*ifaddr).ifa_addr != NULL)
{
int family = ifaddr->ifa_addr->sa_family;
if (family == AF_INET)
{
addr.addr().type = family;
// linux需要添加广播地址而不是ip地址
inet_ntop(AF_INET, &((((sockaddr_in*)((*ifaddr).ifa_addr))->sin_addr)), addr.addr().ip, GP_MAX_IP);
//inet_ntop(AF_INET, &((((sockaddr_in*)(*ifaddr).ifa_broadaddr)->sin_addr)), addr.addr().ip, GP_MAX_IP);
addr.add();
}
}
}
#endif
return ERR_SUCCESS;
}
在CGpNetUdpBroadcast.cpp中进行调用
//
//
void CGpNetUdpBroadcast::appendBroadcastClients(int nProtType)
{
ParamHostAddr haddr; // 这里进行调用
getHostAddrInfo(haddr);
for (INT32 i = 0; i < haddr.count; ++i)
{
ULONG uip = ipToLong(haddr.addrs[i].ip);
if (this->isExsit(uip))
{
//LOGWARNING("CGpNetUdpBroadcast::appendBroadcastClients isExsit ip=[%s]", haddr.addrs[i].ip);
continue;
}
CGpUdpSocketClient* pClient = new CGpUdpSocketClient((SockModeType)nProtType);
if (!pClient)
{
LOGERROR("CGpNetUdpBroadcast::appendBroadcastClients pClient is NULL ip=[%s] nProtType=[%d]", haddr.addrs[i].ip, nProtType);
continue;
}
...
}
初步解决方案
居然是移动一下成员变量:(原因未详)
终极解决方案
字节对齐引发的一场血案!!!
晚上进行了一波头文件包含的精简操作,发现CGpFramePacketAssembly.h和CGpFrameBaseProcess.h头文件一定要包含一个无关的头文件#include "Base/NetBase/GpNetBase.h"当时觉得就很奇怪,引起了特别的注意,为什么无关却还是必须要包含那。当时进行了屏蔽发现只要屏蔽就会出现析构异常崩溃的问题,于是把这个头文件包含的其他头文件进行分类屏蔽。
定位到一定要包含这个IGpNetBase.h这个头文件
继续屏蔽排查,发现一定要包含GpMsgAll.h这个头文件
愈发奇怪,怎么会和数据包的头文件相关那?没道理啊,不解,继续二分法屏蔽排查。
最终发现一定要包含#include "IpToolsMsg/GpMsgIpToolsOperateDevice.h"头文件,该头文件是我们做网络设置模块相关的时候加入的,当时加入后就出现了一些析构异常的问题,一直以为是前置声明的关系引发的。最终在这个文件中发现了字节对齐,引起特别注意,发现没有恢复字节对齐。最终进行恢复测试下来发现不管是win32位还是64位都好了。终于结案了!!!小伙伴们可以安心开发功能了