高手快救我:如何解决多次调用ping 函数而产生的内存泄漏问题?(问题解决,立即结帖,另加200分)
小妹的监测程序需要不停的调用ping 函数,刚开始调用的几十次没有问题,但当调用的次数上百次后竟出现比较大的内存泄漏(我对ping的原理不怎么懂,是不是里面有缓冲区,满了后开始泄漏?),我的ping 函数是由 MSDN 中的例子改写的,调用方法为:
int judge=nPing(IP) 查了两天两夜,无法解决,老板催得紧,小妹今年刚毕业,经验不足,怕丢饭碗,所以恳请各位大哥大姐们帮忙!!!
不胜感激!!!(若哪位有其他得ping 函数请给我一份:qingyin1019@tom.com
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define ICMP_MIN 8 // minimum 8 byte icmp packet (just header)
/* The IP header */
typedef struct iphdr {
unsigned int h_len:4; // length of the header
unsigned int version:4; // Version of IP
unsigned char tos; // Type of service
unsigned short total_len; // total length of the packet
unsigned short ident; // unique identifier
unsigned short frag_and_flags; // flags
unsigned char ttl;
unsigned char proto; // protocol (TCP, UDP etc)
unsigned short checksum; // IP checksum
unsigned int sourceIP;
unsigned int destIP;
}IpHeader;
//
// ICMP header
//
typedef struct _ihdr {
BYTE i_type;
BYTE i_code; /* type sub code */
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
/* This is not the std header, but we reserve space for time */
ULONG timestamp;
}IcmpHeader;
#define STATUS_FAILED 0xFFFF
#define DEF_PACKET_SIZE 32
#define MAX_PACKET 1024
#define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
#define xfree(p) HeapFree (GetProcessHeap(),0,(p))
void decode_resp(char *,int ,struct sockaddr_in *);
void fill_icmp_data(char * icmp_data, int datasize)
{
IcmpHeader *icmp_hdr;
char *datapart;
icmp_hdr = (IcmpHeader *)icmp_data;
icmp_hdr->i_type = ICMP_ECHO;
icmp_hdr->i_code = 0;
icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
icmp_hdr->i_cksum = 0;
icmp_hdr->i_seq = 0;
datapart = icmp_data + sizeof(IcmpHeader);
//
// Place some junk in the buffer.
//
memset(datapart,'E', datasize - sizeof(IcmpHeader));
}
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(USHORT);
}
if(size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
int WaitForEchoReply(SOCKET s)
{
struct timeval Timeout;
fd_set readfds;
readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;
return(select(1, &readfds, NULL, NULL, &Timeout));
}
int nPing(const char * strip)
{
WSADATA wsaData;
SOCKET sockRaw;
struct sockaddr_in dest;
int bread,datasize;
int timeout = 1000;
char *dest_ip;
char *icmp_data;
unsigned int addr=0;
USHORT seq_no = 0;
int nAddrlen = sizeof(struct sockaddr_in);
int nRet;
char *recvbuf;
if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0)
{
return 2;
}
sockRaw = WSASocket (AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,0);
if (sockRaw == INVALID_SOCKET)
{
return 2;
}
bread = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
if(bread == SOCKET_ERROR)
{
return 2;
}
timeout = 1000;
bread = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));
if(bread == SOCKET_ERROR)
{
return 2;
}
memset(&dest,0,sizeof(dest));
addr = inet_addr(strip);
if (addr == INADDR_NONE)
{
return 2;
}
dest.sin_addr.s_addr = addr;
dest.sin_family = AF_INET;
dest_ip = inet_ntoa(dest.sin_addr);
datasize = DEF_PACKET_SIZE;
datasize += sizeof(IcmpHeader);
icmp_data = (char *)xmalloc(MAX_PACKET);
recvbuf = (char *)xmalloc(MAX_PACKET);
if (!icmp_data || !recvbuf)
{
xfree(icmp_data);
xfree(recvbuf);
return 2;
}
memset(icmp_data,0,MAX_PACKET);
fill_icmp_data(icmp_data,datasize);
((IcmpHeader*)icmp_data)->i_cksum = 0;
((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
((IcmpHeader*)icmp_data)->i_seq = seq_no++;
((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,datasize);
bread = sendto(sockRaw, icmp_data, datasize,0,(struct sockaddr*)&dest,sizeof(dest));
if (bread == SOCKET_ERROR)
{
xfree(icmp_data);
xfree(recvbuf);
return ERR_PING;
}
nRet = WaitForEchoReply(sockRaw);
if(!nRet)
{
xfree(icmp_data);
xfree(recvbuf);
return 1;
}
bread = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&dest, &nAddrlen);
if (bread == SOCKET_ERROR)
{
xfree(icmp_data);
xfree(recvbuf);
return 1;
}
xfree(icmp_data);
xfree(recvbuf);
return 0;
}