1

クラスを使用し、ネットワーク接続を開始してリッスンし、新しいクライアントごとに新しいスレッドをスピンオフするC++プログラムを作成しようとしています。

幸い、クラス内からスレッドを生成する方法を理解しましたが、クラスでaccept()を実行しようとすると、セグメンテーション違反が発生します。問題が発生している場所を少しわかりやすくするために、コードを投稿します。

#include <iostream>
#include <string.h> //for memset
#include <pthread>
#include <sys/types.h> //network
#include <sys/socket.h> //network
#include <netinet/in.h> //network

using namespace std;
class network
{
  public:
    void my_listen();
    static void *handleClient(void * in_stream);
};

void* network::handleClient(void * in_stream)
{

  int *stream = reinterpret_cast<int *>(in_stream);
  write(*stream,"Hello Client\n", 12);
}

void network::my_listen()
{
  /*
   * Name: my_listen()
   * Purpose: Listens and accepts new connections. Once accpeted, a new thread
   *          is spun off. 
   * Input: none
   * Output: none
  */

  int *new_socket_desc;
  int port_num = 9876;
  socklen_t client_addr_len;

  int socket_desc = socket(AF_INET,SOCK_STREAM,0);

  sockaddr_in serv_addr, cli_addr;

  if(socket_desc == -1)
  {
    cerr << "Unable to create new sockets\n";
  }

  memset(&serv_addr, 0, sizeof(serv_addr));

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(port_num);

  if(bind(socket_desc, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
  {
    cerr << "Error on binding " << port_num << endl;
  }

  listen(socket_desc,5);

  client_addr_len = sizeof(cli_addr);

  pthread_t thread[10];
  int count = 0;

  *new_socket_desc = accept(socket_desc, (struct sockaddr *) &cli_addr, &client_addr_len); //Right here I segment fault

  cout << "Connected client " << " @ " << new_socket_desc << " (" << *new_socket_desc << ")" <<  endl;

  pthread_create(thread[0], handleClient, (void *)new_socket_desc);

  pthread_join(thread[0],NULL);
}

メインはそれほどエキサイティングではありません:

#include "network.h"
using namespace std;

int main()
{
  network my_network;

  my_network.my_listen();
}

興味深いのは、クラスを使用せずにこれらすべてを機能させることができることです。スコープと関係があると思いますが、理由はわかりません。

ちなみに、私はx86_64のターゲットプラットフォームでgcc4.6.2を使用しています

4

2 に答える 2

2

new_socket_descをポインタとして宣言しますが、それが指しているものを設定することはありません。ポインタの場所に値を入れようとすると(accept呼び出しの結果とともに)、メモリ内のランダムな場所に書き込みが行われるため、すぐにクラッシュする場合と発生しない場合があります(このバージョンのコードではクラッシュを引き起こします)が、常に非常に悪いです。

new_socket_descをクラスの通常のintメンバーにし、スレッドを作成するときに&演算子を使用します。それ以外の場合は*演算子を使用しないでください。幸運を祈る必要があります。

于 2012-09-23T14:33:36.910 に答える
1
int *new_socket_desc;
// ....
*new_socket_desc = accept(socket_desc ....

new_socket_descを単一化されたポインタとして宣言し、の結果を。でaccept示されるランダムなメモリ位置に割り当てnew_socket_descます。したがって、明らかにこれによりSEGFAULTが発生します。やったほうがいい:

int new_socket_desc;
// ....
new_socket_desc = accept(socket_desc ....
于 2012-09-23T16:09:11.620 に答える