我在 Windows 环境下使用 Codeblocks/Mingw 和 GNU GCC 编译器编写 C 程序时遇到问题。
我正在尝试实现一个 TCP 服务器库,它允许同时创建和管理多个服务器。
我创建了一些结构来管理服务器:
typedef struct
{
BOOL bExitThread;
HANDLE hThread;
}TagThreadControl;
typedef struct
{
SOCKET sSocket;
int iMaxReceiveLengthPerMessage;
struct in_addr tagIPAddress;
USHORT usPort;
TagThreadControl tagThread;
TagQueue *ptagReveivedMessages;
}TagConnection_Internal;
typedef struct
{
BOOL bInternalProcessingActive;
UINT uiID;
SOCKET sSocket;
TagConnection_Internal *ptagConnections;
WSADATA tagWsa;
struct sockaddr_in tagServerInfo;
TagThreadControl tagThreadGetNewConnections;
int iMaxBacklog;
int iMaxConnections;
int iConnectionCount;
}TagServer;
无论如何,atm 我专注于只运行一个,但在使用函数 _beginthreadex 时遇到了问题。当我调用它时,它返回一个有效的句柄(!NULL)并在启动线程时在内部崩溃。使用以下函数创建一个新服务器:
UINT uiTCPServer_Init_g(unsigned short usDestinationPort,
int iMaxReceiveLengthPerMessage,
int iMaxConnectionsCount,
int iMaxBacklogCount)
{
UINT uiNewID;
int iIndex;
WSADATA tagWsa;
/* First Server */
if(iServerCount_m==0)
{
if(!bIDGenerator_Init_g(100))
{
printf("bIDGenerator_Init_g(): failed\n");
return(INVALID_SERVER_HANDLE);
}
if(!bIDGenerator_GetNewID_g(&uiNewID))
{
printf("bIDGenerator_GetNewID_g(): failed\n");
return(INVALID_SERVER_HANDLE);
}
printf("Got ID: %d\n",uiNewID);
if(!(ptagServer_m=malloc(sizeof(TagServer))))
return(INVALID_SERVER_HANDLE);
if(!(ptagServer_m->ptagConnections=malloc(sizeof(TagConnection_Internal)*iMaxConnectionsCount)))
{
return(INVALID_SERVER_HANDLE);
}
/* Winsock DLL initislisieren */
if(WSAStartup(MAKEWORD(2,2),&tagWsa)!= 0)
{
printf("Init failed with error: %d\n",WSAGetLastError());
return(INVALID_SERVER_HANDLE);
}
printf("Initialised\n");
}
else
{
//TODO: Implement list, for multiple servers
printf("**NOT IMPLEMENTED!**\n");
return(INVALID_SERVER_HANDLE);
}
for(iIndex=0;iIndex<iMaxConnectionsCount;++iIndex)
ptagServer_m[iServerCount_m].ptagConnections[iIndex].iMaxReceiveLengthPerMessage=iMaxReceiveLengthPerMessage;
/* Create Socket for listening.. */
if((ptagServer_m[iServerCount_m].sSocket = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
{
printf("uiTCPServer_Init_g(): Failed to create Socket: %d\n",WSAGetLastError());
if(iServerCount_m==0)
WSACleanup();
return(INVALID_SERVER_HANDLE);
}
printf("Socket created\n"); // TODO: remove this
ptagServer_m[iServerCount_m].tagServerInfo.sin_family = AF_INET;
ptagServer_m[iServerCount_m].tagServerInfo.sin_addr.s_addr = INADDR_ANY;
ptagServer_m[iServerCount_m].tagServerInfo.sin_port = htons(usDestinationPort);
ptagServer_m[iServerCount_m].iMaxBacklog=iMaxBacklogCount;
ptagServer_m[iServerCount_m].iMaxConnections=iMaxConnectionsCount;
/* Socket binden */
if(bind(ptagServer_m[iServerCount_m].sSocket,
(struct sockaddr*)&ptagServer_m[iServerCount_m].tagServerInfo,
sizeof(ptagServer_m[iServerCount_m].tagServerInfo)) == SOCKET_ERROR)
{
printf("Bind failed: %d\n",WSAGetLastError());
if(iServerCount_m==0)
WSACleanup();
return(INVALID_SERVER_HANDLE);
}
printf("Bind done\n"); // TODO: remove this
ptagServer_m[iServerCount_m].uiID=uiNewID;
++iServerCount_m;
return(uiNewID);
这是创建后调用的函数,该函数在调用 _beginthreadex 时崩溃:
BOOL bTCPServer_StartListening_g(UINT uiServerID)
{
UINT uiThreadID;
TagServer *ptagCurrServer=ptagGetServerByID_m(uiServerID);
if(!ptagCurrServer)
return(FALSE);
/* Start listen on socket */
if(listen(ptagCurrServer->sSocket,
ptagCurrServer->iMaxBacklog) == SOCKET_ERROR)
{
printf("listen(): failed\n");
return(FALSE);
}
printf("listen on socket started...\n"); // TODO: remove this
ptagCurrServer->tagThreadGetNewConnections.bExitThread=FALSE;
if(!(ptagCurrServer->tagThreadGetNewConnections.hThread=(HANDLE)_beginthreadex(NULL,
0,
&Thread_GetNewConnections_m,
(void*)ptagCurrServer,
0,
&uiThreadID)))
{
printf("_beginthreadex(): failed starting Thread_GetNewConnections_m");
return(FALSE);
}
printf("_beginthreadex() returned valid handle\n"); // TODO: remove this
Sleep(2000); //Without that Sleep, returns successful and crashes after
printf("started listening thread\n"); // TODO: remove this
return(TRUE);
}
新线程中调用的函数如下所示:
unsigned __stdcall Thread_GetNewConnections_m(void *pvParam)
{
TagServer *ptagCurrServer=(TagServer*)pvParam;
struct sockaddr_in tagClientInfo;
int iSocketSize=sizeof(struct sockaddr_in);
int iFreeConnectionIndex;
UINT uiThreadID;
if(!ptagCurrServer)
{
printf("Thread_GetNewConnections_m(): Terminated in an unusual way\n");
return(0);
}
printf("started Thread_GetNewConnections_m()...\n"); // TODO: remove this
memset(ptagCurrServer->ptagConnections,0,sizeof(TagConnection_Internal)*ptagCurrServer->iMaxConnections);
while(!ptagCurrServer->tagThreadGetNewConnections.bExitThread)
{
printf("Getnewcons...\n"); // TODO: remove this
vCleanUpDeadConnections_m(ptagCurrServer);
// TODO: clean up dead connections here...
if(ptagCurrServer->iConnectionCount >= ptagCurrServer->iMaxConnections)
{
printf("Max Connections reached\n");
Sleep(100);
continue;
}
if((iFreeConnectionIndex=iTCPServer_GetNextFreeConnectionIndex_m(ptagCurrServer->ptagConnections,ptagCurrServer->iMaxConnections)) <0)
{
printf("iTCPServer_GetNextFreeConnectionIndex_m(): failed (Should not happen)\n");
Sleep(100);
continue;
}
printf("next free connection index: %d\n",iFreeConnectionIndex);
if((ptagCurrServer->ptagConnections[iFreeConnectionIndex].sSocket=accept(ptagCurrServer->sSocket,(struct sockaddr*)&tagClientInfo,&iSocketSize)) == INVALID_SOCKET)
{
printf("accept(): failed\n"); // TODO: Don't return, handle error somehow
Sleep(10);
continue;
}
printf("New connection established\n");
++ptagCurrServer->iConnectionCount;
/* Store Data from client */
memcpy(&ptagCurrServer->ptagConnections[iFreeConnectionIndex].tagIPAddress,&tagClientInfo.sin_addr,sizeof(struct in_addr));
ptagCurrServer->ptagConnections[iFreeConnectionIndex].usPort=ntohs(tagClientInfo.sin_port); //Convert form Network to host short
/* Start Thread for new Connection */
if((ptagCurrServer->ptagConnections[iFreeConnectionIndex].tagThread.hThread=(HANDLE)_beginthreadex(NULL,
0,
Thread_ConnectionHandler_m,
&ptagCurrServer->ptagConnections[iFreeConnectionIndex],
0,
&uiThreadID))==NULL)
{
printf("_beginthreadex(): failed to start Thread for new connection\n");
--ptagCurrServer->iConnectionCount;
closesocket(ptagCurrServer->ptagConnections[iFreeConnectionIndex].sSocket);
Sleep(100);
continue;
}
Sleep(10);
}
return(0);
}
有趣的是,每当我在这个函数中注释整个代码(不包括 return(0))并且只在那里留下一个 printf() 时,程序仍然崩溃,甚至没有进入该函数。我包含了以下头文件,其中一些是我自己创建的:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <process.h>
#include <windows.h>
#include <winsock2.h>
如果我尝试运行编译后的程序,跟踪将如下所示:
Curr index 0 (0), used: FALSE
Got ID: 1
Initialised
Socket created
Bind done
listen on socket started...
_beginthreadex() returned valid handle
使用线程是否需要任何其他编译器标志/头文件...?
如果需要更多信息,请告诉我。
问候,XXXBold
最佳答案
我解决了这个问题,另一个错误调用 malloc() 的函数损坏了内存,可以使用 Dr Memory 解决问题
关于c - _beginthreadex() 返回有效句柄,并在使用 Codeblocks/Mingw 和 GNU GCC 编译器执行线程时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41650864/