我正在使用Winsock UDP套接字在C ++中编写网络游戏,我遇到的问题是每次调用sendto()时都会以不可逆转的方式增加内存使用量。最奇怪的是,只出现在客户端上,即使它使用几乎相同的网络代码,服务器也没有问题。
这是一个客户端类的构造函数,其中创建了连接(我无法显示整个代码,因为它更大,而且它不是开源项目):
Client(){
nospawn = true;
status = 0;
hThread = 0;
firstrs = NULL;
lastrs = NULL;
if (WSAStartup(0x0101, &rdata) != 0) exit(WSAGetLastError());
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd == INVALID_SOCKET) exit(WSAGetLastError());
gethostname(host_name, sizeof(host_name));
hp = gethostbyname(host_name);
FILE * file;
BYTE * data;
fopen("config.txt", "rb" );
data= (BYTE*)malloc (15);
fread( data, 15, 1, file );
fclose( file );
memset((void *)&server, '\0', sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(8334);
server.sin_addr.S_un.S_un_b.s_b1
= (unsigned char)(((int)data[0]-48)*100+((int)data[1]-48)*10+(int)data[2]-48);
server.sin_addr.S_un.S_un_b.s_b2
= (unsigned char)(((int)data[4]-48)*100+((int)data[5]-48)*10+(int)data[6]-48);
server.sin_addr.S_un.S_un_b.s_b3
= (unsigned char)(((int)data[8]-48)*100+((int)data[9]-48)*10+(int)data[10]-48);
server.sin_addr.S_un.S_un_b.s_b4
= (unsigned char)(((int)data[12]-48)*100+((int)data[13]-48)*10+(int)data[14]-48);
/* Clear out client struct */
memset((void *)&client, '\0', sizeof(struct sockaddr_in));
client.sin_family = AF_INET;
client.sin_port = htons(0);
client.sin_addr.S_un.S_un_b.s_b1 = hp->h_addr_list[0][0];
client.sin_addr.S_un.S_un_b.s_b2 = hp->h_addr_list[0][1];
client.sin_addr.S_un.S_un_b.s_b3 = hp->h_addr_list[0][2];
client.sin_addr.S_un.S_un_b.s_b4 = hp->h_addr_list[0][3];
server_length = sizeof(struct sockaddr_in);
if (bind(sd, (struct sockaddr *)&client, sizeof(struct sockaddr_in))==-1){
closesocket(sd);
WSACleanup();
exit(WSAGetLastError());
};
}`
将数据发送到服务器的功能:
void sendCRequest(){
int sum = 0;
unsigned char c1,c2,c3,c4;
if (ludzie[0].ster[S_RIGHT]) sum+=1;
if (ludzie[0].ster[S_LEFT]) sum+=2;
if (ludzie[0].ster[S_UP]) sum+=4;
if (ludzie[0].ster[S_DOWN]) sum+=8;
if (ludzie[0].ster[S_RUN]) sum+=16;
if (ludzie[0].ster[S_ENTER]) sum+=32;
if (ludzie[0].ster[S_SHOT]) sum+=64;
if (ludzie[0].ster[S_RELOAD]) sum+=128;
if (ludzie[0].ster[S_SHOT]){
float depth;
GLdouble modelMatrix [16];
GLdouble projMatrix [16];
GLdouble dx,dy,dz;
GLint viewport [4];
glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
glGetIntegerv(GL_VIEWPORT,viewport);
glReadPixels( mx, screendy*2-my, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
gluUnProject(mx,screendy*2-my,depth,modelMatrix,projMatrix,viewport,&dx,&dy,&dz);
//x
floatEnc(dx,&c1,&c2,&c3,&c4);
data[16]=c1; data[17]=c2; data[18]=c3; data[19]=c4;
//y
floatEnc(dy,&c1,&c2,&c3,&c4);
data[20]=c1; data[21]=c2; data[22]=c3; data[23]=c4;
//z
floatEnc(dz,&c1,&c2,&c3,&c4);
data[24]=c1; data[25]=c2; data[26]=c3; data[27]=c4;
}
data[0] = 'C';
for (int i=1;i<9;i++) data[i]=auth[i-1];
data[10] = (char)sum;
data[11]=ludzie[0].ster[S_SPACE]?'1':'0';
floatEnc(ludzie[0].r,&c1,&c2,&c3,&c4);
data[12]=c1; data[13]=c2; data[14]=c3; data[15]=c4;
sendto(sd, data, RQBUFFER, 0, (struct sockaddr *)&server, server_length);
}
如果除了sendto()之外还有其他内容,则没有内存泄漏,因此其余代码不是问题。这些OpenGL调用和floatEnc(它将浮点数编码为4个字节)也不重要,没有sendto()一切正常。除了不使用Winsock / UDP或每次内存使用率过高时再次销毁和创建套接字时,是否还有其他可能的修复方法?
答案 0 :(得分:0)
Client()
确实存在内存泄漏。您调用malloc
但未调用free
来释放内存。我建议您使用std::vector
或至少new
和delete
。除此之外,您的问题中包含的代码中没有其他泄漏。我怀疑你的程序中有其他代码执行同样的事情Client()
- 调用malloc
而不调用free
来释放内存。
至于你认为被sendto
泄露的内存,你应该知道Winsock库在用户空间中做了很多事情,包括分配内存。 Winsock库很可能为各种缓冲区分配内存并保留它们以备将来使用。