2017-01-14 7 views
-1

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

+0

を使用して問題を解決できます。 – rubenvb

+0

@rubenvbあなたの答えをありがとう、私はちょうど私のプロジェクトのコンパイラオプションにそのオプションを追加しましたが、以前と同じ結果を得ます。 – XXXBold

+0

"gcc -v"は何を出力しますか? – rubenvb

答えて

0

I)は、malloc関数の誤ったコール(と別の関数を、問題を解決し、メモリを破損し、あなたが-mthreadsフラグで/リンクをコンパイルする必要があるかもしれませんDr Memory

+0

あなたの自動応答はスパムの種子のように疑わしいようです。 – Steve

+0

心配はありません。将来的にはもっと具体的になるべきだと思いますが、それが最初に投稿しなかったコードの別の部分であるため、少し面倒なことがあります。 – XXXBold

関連する問題