2012-09-07 3 views
0

나는 다음과 같은 코드가 있습니다표준 : : 벡터에 소켓 객체를 이동할 수 없습니다

try 
{ 
    HAS::TCPServerSocket servSock(echoServPort); // Socket descriptor for server 
    std::vector<HAS::TCPSocket*> sockets(MAXCONN); 
    for (;;) 
    { 
     try 
     { 
      if (socketCount < MAXCONN) 
      { 
       HAS::TCPSocket* sock(servSock.accept()); 
       sockets.push_back(sock); 
       std::thread handler(handleTCPClient, std::ref(sockets[socketCount++])); 
       handler.detach(); 
      } 
     } 
     catch (...) 
     { 
      cerr << "Unable to create thread" << endl; 
      exit(1); 
     } 
    } 
} 

내가 연결 (MAXCONN=4) 제한된 수의 트랙을 유지하려면 및 std::vector을 사용하여 열 소켓 추적하려는를 . 여하튼, 위의 코드를 사용할 때 sock 변수가 servSock.accept()으로 허용되는 현재 소켓으로 올바르게 설정됩니다. 그러나 std::vectorsock 변수를 푸시하려고하면 양말 객체가 느슨합니다.

복사 및/또는 이동 생성자를 올바르게 지정해야한다는 느낌이 들지만 양쪽 모두를 정의하고 호출 될 때 구분 점을 사용했지만 전혀 호출되지 않는 것 같습니다. .

+0

std :: vector 소켓 (MAXCONN); 벡터를 최대 크기 4로 초기화해야합니까? ... 어떻게 벡터가 작동 해야하는지 아닙니다. – Alex

+0

'socketCount'가 최대 크기에 도달하면 프로그램은 busy-loop가됩니다. 그것은 끔찍한 생각처럼 보입니다. 또한, 언제'socketCount'가 * 감소 될 것입니까? –

+2

'std :: vector 소켓 (MAXCONN);'은 네 개의 널 포인터를 포함하도록 벡터를 초기화 할 것이고, 최대 크기로는 아무것도하지 않을 것이다. –

답변

4

push_back이라고 말하면 벡터 요소에 대한 참조가 무효화됩니다. 당신은 당신이 가진 방식대로 코드를 사용할 수 없습니다. 먼저 전체 벡터를 채운 다음 다시 만지지 마십시오. 또는 요소 참조가 컨테이너 변형 (일반적으로 list 또는 multiset 또는 unordered_multiset, 끝 부분에 삽입/삭제에 deque)으로 무효화되지 않는 컨테이너를 사용하십시오.

또는 포인터를 스레드에 전달하십시오.

+0

도움에 감사드립니다. std :: list 잘 작동하는 것 같습니다. 또한 포인터를 스레드에 전달하기 전에 시도 - 나는 그것에 대해 갈 수있는 최선의 방법이 될 것이라고 생각하지만, 그것을 작동시키지 못했습니다. 다시 시도 할 것입니다 :) – QNimbus

+0

@QNimbus : 코드에 다른 많은 문제가 있습니다. 나는 사본을 전달하는 것이 왜 효과가 없는지를 보지 못했으며, 그것은 가장 쉽고 가장 적절한 해결책입니다. –

+1

@QNimbus : 마지막 줄의 조언을 따르십시오. 나머지 답변보다 낫습니다. 당신은 소켓에 대한 포인터를 잡고 단지 * copy * 포인터를 가지므로 특별한 이유없이 (포인터를 수정하기 위해'thread'가 필요하지 않는 한) 포인터에 대한 참조를 가질 필요가 없습니다. –

2
std::vector<HAS::TCPSocket*> sockets(MAXCONN); 
... 
sockets.push_back(sock); 
std::thread handler(handleTCPClient, std::ref(sockets[socketCount++])); 

그 코드는 재미있어 보입니다. 벡터에는 4 개의 null 포인터가 있고 그 뒤에는 push_back() 호출과 함께 끝에 추가 된 실제 포인터가옵니다. 스레드는 원하는 실제 포인터가 아닌 첫 번째 널 포인터에 대한 참조를 얻습니다.

다음 두 가지 중 하나를 수행 할 수 있습니다. 제 제안은 reserve()을 호출하여 push_backs으로 이터레이터를 무효화하는 재 할당을 보장합니다. 그것은 문제를 해결할 것입니다. 또는 요소를 사용하여 벡터를 만들 수 있지만 push_back()을 호출하지 말고 operator[]을 사용하여 socketCount 위치의 요소를 수정합니다.

관련 문제