0

我正在使用 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 或每次内存使用率过高时再次销毁和创建套接字之外,还有其他可能的修复方法吗?

4

1 回答 1

0

你确实有内存泄漏Client()。你打电话malloc但不是打电话free来释放内存。我建议std::vector为此使用或至少使用newand delete。除此之外,您在问题中包含的代码中没有其他泄漏。我怀疑你的程序中有其他代码做同样的事情Client()- 调用malloc而不调用free释放内存。

至于您认为正在泄漏的内存,sendto您应该知道 Winsock 库在用户空间中做了很多事情,包括分配内存。Winsock 库很可能正在为各种缓冲区分配内存并保留它们以供将来使用。

于 2013-06-04T21:32:05.347 回答