Windows環境でCodeblocks/MingwをGNU GCCコンパイラで使用しているCプログラムに問題があります。_beginthreadex()は、GNU GCCコンパイラでCodeblocks/Mingwを使用してスレッドを実行すると有効なハンドルとクラッシュを返します。
私は複数のサーバーを同時に作成して管理することができる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;
、気圧私は実行するために単一のものをもたらすに焦点を当てています、と私は、関数_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);
}
おかしい事ですが、私は(この関数内だけのprintfを残す)が、プログラムの開発はまだクラッシュ、Eなし((0)リターンを除く)全体のコードをコメントしたときに機能に入る。私は、次のヘッダファイルを用意しました、といくつかは、自分自身を作成しました:私は私のコンパイル済みのプログラムの開発を実行しようとすると、以下のように、トレースが見え
#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
を使用して問題を解決できます。 – rubenvb
@rubenvbあなたの答えをありがとう、私はちょうど私のプロジェクトのコンパイラオプションにそのオプションを追加しましたが、以前と同じ結果を得ます。 – XXXBold
"gcc -v"は何を出力しますか? – rubenvb