C ++ 재정의 헤더 파일 (winsock2.h)


143

헤더 파일을 두 번 포함하지 못하게하려면 어떻게합니까? 문제는 내가 포함하고 있습니다에서 MyClass.h 후 나는 포함하고있어 에서 MyClass.h 이 여러 번 포함하고 재정의 오류가 발생하므로, 많은 파일을. 방지하는 방법?

경비원을 포함시키는 대신 #pragma를 한 번 사용하고 있는데 괜찮습니다.

MyClass.h :

// MyClass.h
#pragma once

#include <winsock2.h>

class MyClass
{

// methods
public:
 MyClass(unsigned short port);
 virtual ~MyClass(void);
};

편집 : 내가 얻는 오류 중 몇 가지

c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(91) : warning C4005: 'AF_IPX' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(460) : see previous definition of 'AF_IPX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(124) : warning C4005: 'AF_MAX' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(479) : see previous definition of 'AF_MAX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(163) : warning C4005: 'SO_DONTLINGER' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(402) : see previous definition of 'SO_DONTLINGER'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(206) : error C2011: 'sockaddr' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(485) : see declaration of 'sockaddr'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing '}' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing ';' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2059: syntax error : 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C2143: syntax error : missing ';' before '}'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(518) : warning C4005: 'IN_CLASSA' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(287) : see previous definition of 'IN_CLASSA'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(524) : warning C4005: 'IN_CLASSB' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(293) : see previous definition of 'IN_CLASSB'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(530) : warning C4005: 'IN_CLASSC' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(299) : see previous definition of 'IN_CLASSC'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(541) : warning C4005: 'INADDR_ANY' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(304) : see previous definition of 'INADDR_ANY'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(543) : warning C4005: 'INADDR_BROADCAST' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(306) : see previous definition of 'INADDR_BROADCAST'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(577) : error C2011: 'sockaddr_in' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(312) : see declaration of 'sockaddr_in'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(132) : error C2011: 'fd_set' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(68) : see declaration of 'fd_set'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(167) : warning C4005: 'FD_SET' : macro redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(102) : see previous definition of 'FD_SET'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(176) : error C2011: 'timeval' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(111) : see declaration of 'timeval'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(232) : error C2011: 'hostent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(167) : see declaration of 'hostent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(245) : error C2011: 'netent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(180) : see declaration of 'netent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(252) : error C2011: 'servent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(187) : see declaration of 'servent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(264) : error C2011: 'protoent' : 'struct' type redefinition
        c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(199) : see declaration of 'protoent'

4
이미 #pragma를 한 번 사용하고 있으므로 한 번만 포함해야합니다.
Naveen

1
컴파일러가 pragma를 한 번 지원하지 않습니까?
Svetlozar Angelov

Visual Studio 2008을 사용하고 있는데 왜 <winsock2.h>가 두 번 포함됩니까?
akif September

1
MyClass.h
Svetlozar Angelov에

5
winsock2와 winsock에는 공통 구조가 있습니다. 당신이 아니라 모두 그들 중 하나, 포함해야
Svetlozar 앙겔

답변:


234

이 문제는 <windows.h>before를 포함 할 때 발생 <winsock2.h>합니다. 당신이 목록에 포함 주선 시도 <windows.h>후 포함 <winsock2.h>또는 정의 _WINSOCKAPI_를 먼저 :

#define _WINSOCKAPI_    // stops windows.h including winsock.h
#include <windows.h>
// ...
#include "MyClass.h"    // Which includes <winsock2.h>

참조 .


<windows.h>를 전혀 포함시키지 않고 <winsock2.h>가 나를 위해한다는 것을 알고 있습니다.
akif September

2
나를 위해 코드 <winsock2.h>는 MSVC2008 에서만 정상적으로 컴파일됩니다 . <windows.h>포함하면 제공 한 것과 동일한 컴파일 오류가 발생합니다.
pingw33n

<windows.h>가 stdafx.h에 포함되어 있습니까?
콜린 데스몬드

1
이 솔루션은 SDK 7.1이 설치된 VS 2010의 문제를 해결했습니다. 감사합니다 pingw33n!
adamfisk

나는 #include <winsock2.h> #include <ws2tcpip.h> #include <windows.h>순서를 가지고 winsock2를 얻었습니다 .h 파일을 찾을 수 없습니다. 포함 #define _WINSOCKAPI_ 3 위는 여전히 같은 오류를 포함
에바

75

다른 사람들이 제안했듯이 문제는 windows.h이전에 포함될 때 입니다 WinSock2.h. windows.h포함 하기 때문에 winsock.h. 둘 다 사용할 수 없습니다 WinSock2.hwinsock.h.

솔루션 :

  • WinSock2.h전에 포함하십시오 windows.h. 미리 컴파일 된 헤더의 경우이를 해결해야합니다. 간단한 프로젝트의 경우 쉽습니다. 그러나 큰 프로젝트 (특히 미리 컴파일 된 헤더없이 휴대용 코드를 작성할 때)에는 헤더 WinSock2.h가 포함되어 있을 때 windows.h다른 헤더 / 구현 파일에서 이미 포함 될 수 있기 때문에 매우 어려울 수 있습니다.

  • 정의 WIN32_LEAN_AND_MEAN하기 전에 windows.h또는 넓은 전망이다. 그러나 그것은 당신이 필요로 할 수있는 많은 다른 것들을 배제 할 것이고 당신은 그것을 스스로 포함시켜야합니다.

  • 정의 _WINSOCKAPI_하기 전에 windows.h또는 넓은 전망이다. 그러나 포함 WinSock2.h하면 매크로 재정의 경고가 나타납니다.

  • 사용 windows.h대신 WinSock2.h하는 경우 winsock.h(대부분의 경우입니다) 프로젝트에 충분하다. 컴파일 시간이 길어 지지만 오류 / 경고는 해결됩니다.


14
WIN32_LEAN_AND_MEAN저에게 탱크를위한 솔루션이었습니다
Jonatan Cloutier

_WINSOCK_솔루션 정보 : 두 정의가 모두 동일한 경우 매크로 재정의 경고를 표시해서는 안됩니다. 일반적인 버그는 사람들이 값을 설정하지 않고 프로젝트에 정의를 추가하고 빈 정의를 기대한다는 것입니다. 그러나 -D_WINSOCK_cmd 행에 추가 하면 _WINSOCK_1로 설정 됩니다. 빈 정의를 작성하려면 -D_WINSOCK_=전달해야합니다.
Paweł Stankowski

를 사용하는 경우 상황에 따라이 #define _WINSOCKAPI_필요할 수도 있습니다 #define _WINSOCK_DEPRECATED_NO_WARNINGS.
Lorien Brune

16

아-Windows의 추악함 ... 포함 순서가 중요합니다. windows.h 앞에 winsock2.h를 포함시켜야합니다. windows.h는 미리 컴파일 된 헤더 (stdafx.h)에 포함되어 있으므로 winsock2.h를 포함시켜야합니다.

#include <winsock2.h>
#include <windows.h>

14

"헤더 가드"를 사용하여 :

#ifndef MYCLASS_H
#define MYCLASS_H

// This is unnecessary, see comments.
//#pragma once

// MyClass.h

#include <winsock2.h>

class MyClass
{

// methods
public:
    MyClass(unsigned short port);
    virtual ~MyClass(void);
};

#endif

2
나는 내가 틀렸다고 생각한다. (지금까지 4 upvotes) include guard를 사용하는 것이 pragma와 한 번 같다고 생각한다.
Svetlozar Angelov

1
글쎄, #pragma가 있는데 afaik이 같은 헤더 가드입니다
akif

2
@ Angelov : 예, 그것이 그들이 같은 말이라고 말하는 것입니다. 내 헤더 파일에는 문제가 없지만 <winsock2.h> 자체에는 헤더 가드가 없거나 다른 것일 수 있습니다.
akif September

1
정의에 따르면 #pragma는 컴파일러에 따라 다릅니다 (비표준). 모든 컴파일러에서 작동하지 않을 수 있습니다. Visual Studio에서 #pargma를 한 번만 허용한다는 것을 알고 있습니다. gcc가 있는지 확실하지 않습니다. 경비원이 항상 일한다는 것을 알고 있습니다. #pragma를 한 번 사용하고 최대한의 번영을 위해 가드를 포함시킵니다. MSVC는 #pragma의 처리를 한 번 최적화했으며 gcc는 include guard의 처리를 최적화 한 것으로 보입니다. 표준 헤더와의 유일한 차이점은 #praga가 한 번 포함 가드 외부에 있다는 것입니다.
KitsuneYMG

1
'#pragma'명령은 임의의 구현 정의 효과를 갖도록 ANSI 표준에 지정되어 있습니다. GNU C 전 처리기에서 '#pragma'는 먼저 게임 'rogue'를 실행하려고 시도합니다. 실패하면 게임 'hack'을 실행하려고 시도합니다. 실패하면 하노이 타워를 표시하는 GNU Emacs를 실행하려고 시도합니다. 실패하면 치명적인 오류를보고합니다. 어쨌든 전처리는 계속되지 않습니다.
-Richard

6

헤더의 혼란에 어딘가에 windows.h를 포함하는 타사 패키지를 가져 오려고 할 때이 문제가 발생했습니다. _WINSOCKAPI_프로젝트 수준에서 정의 하는 것은 수프를 넘어 가고 문제가있는 포함을 수정하는 것보다 훨씬 쉬웠습니다 (더 유지 관리하기 쉬운 것은 아닙니다).


1
Qt의 .pro 파일에서 다음과 같이 보입니다. DEFINES += _WINSOCKAPI_
phyatt

@ phyatt : 내가하지 않으면 대답으로 바꿔야합니다!
Leif Gruenwoldt

@LeifGruenwoldt 가자! 기꺼이 도와 드리겠습니다.
phyatt

6

VS 2015에서는 다음이 작동합니다.

#define _WINSOCKAPI_

다음은 그렇지 않습니다.

#define WIN32_LEAN_AND_MEAN

6

나는 (재귀 적으로) 포함 헤더 파일을 발견, 재귀 포함 검사 일부 #include "windows.h"#include "Winsock.h"와 쓰기 #include "Winsock2.h". 이 파일에 추가했습니다#include "Winsock2.h" 에서 첫 번째 포함으로 했습니다.

인내심의 문제가 포함 모습에 하나씩 먼저,이 순서를 설정 #include "Winsock2.h"한 후#include "windows.h"


5

나는이 링크 windows.h와 winsock2.h 를 발견 했다.

#define _WINSOCKAPI_    // stops windows.h including winsock.h
#include <windows.h>
#include <winsock2.h>

문제가 발생한 위치를 찾는 데 문제가 있었지만 #define을 추가하여 파악하지 않고도 빌드 할 수있었습니다.


4

FILENAME_H 만 사용하지는 않지만

#ifndef FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD
#define FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD

//code stuff
#endif // FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD

나는 항상 postfix guid를 사용했다. 몇 년 전에 파일 이름이 같고 가드를 포함하는 다른 헤더 파일이있는 매우 열악한 코드베이스를 발견했습니다. 해당 파일은 동일한 이름의 클래스를 정의했습니다. 네임 스페이스 만 사용 된 경우 일부 프로젝트는 일부를 컴파일하지 않았습니다. 고유 가드를 사용하는 것은 헤더와 내용을 차별화하는 솔루션의 일부였습니다.

Visual Studio가 설치된 Windows의 경우 Linux uuidgen -t에서 guidgen.exe를 사용하십시오.


4

나는 같은 문제를 겪었고 여기에 내가 지금까지 발견 한 것이 있습니다.

이 출력 조각에서-

c : \ program files \ microsoft sdks \ windows \ v6.0a \ include \ ws2def.h (91) : 경고 C4005 : 'AF_IPX': 매크로 재정의
c : \ program files \ microsoft sdks \ windows \ v6.0a \ include \ winsock.h (460) : 'AF_IPX'의 이전 정의 참조

-솔루션에 ws2def.h와 winsock.h가 모두 포함 된 것으로 보입니다.

ws2def.h 파일을 보면 다음 주석으로 시작합니다.

/*++

Copyright (c) Microsoft Corporation. All rights reserved.

Module Name:

    ws2def.h

Abstract:

    This file contains the core definitions for the Winsock2
    specification that can be used by both user-mode and 
    kernel mode modules.

    This file is included in WINSOCK2.H. User mode applications
    should include WINSOCK2.H rather than including this file
    directly. This file can not be included by a module that also
    includes WINSOCK.H.

Environment:

    user mode or kernel mode

--*/

마지막 줄에주의를 기울이십시오- "이 파일은 WINSOCK.H를 포함하는 모듈에는 포함되지 않습니다"

여전히 코드를 변경하지 않고 문제를 해결하려고합니다.

이것이 의미가 있는지 알려주십시오.


2

헤더 가드를 사용해야합니다.

그 줄을 헤더 파일의 맨 위에 놓으십시오

#ifndef PATH_FILENAME_H
#define PATH_FILENAME_H

그리고 바닥에

#endif

1
#pragma once and guards is 같지 않습니까?
akif September

헤더 가드는 전 처리기 수준에서 파일이 다시 포함되는 것을 막을뿐 아니라 #pragma보다 한 번 더 휴대하기 쉽습니다.
Timo Geusch

1
나는 그들이 같은 목적으로 건축되었다는 것을 의미했다 :)
akif

2
#pragma once is a standard, afaik
ntcong

2

#pragma once파일 이름의 전체 경로를 기반으로합니다. 따라서 다른 디렉토리에 MyClass.h 또는 Winsock2.h와 동일한 두 개의 사본이 있습니다.


심볼릭 링크 또는 NTFS 정션도 시스템을 손상시킵니다.
Thomi

1

#pragma once은 MS 컴파일러에서도 결함이 있으며 다른 많은 컴파일러에서 지원하지 않습니다. 다른 많은 사람들이 언급했듯이 include guard를 사용하는 것이 좋습니다. 전혀 사용하지 마십시오 #pragma once. 인생이 훨씬 쉬워집니다.


3
불행히도, 오타가 가드가 실제로 작동하지 않음을 의미하거나 다른 디렉토리에있는 같은 이름의 파일이 동일한 토큰을 사용하거나 사용 된 토큰이 이중으로 시작하는 곳에서 0 번 이상 포함 된 가드를 보았습니다. 밑줄 또는 밑줄은 대문자로 표시됩니다 (따라서 #pragma처럼 한 번만 이식 할 수 없음). 따라서 winsock.h를 사용하는 것과 같이 본질적으로 이식 할 수없는 코드의 경우 #pragma에 의해 한 번 문제가되었다고 생각했습니다. 전혀 지원되지 않는 것 외에는 언제 실패합니까?
Steve Jessop

3
를 사용할 때 #pragma once컴파일러는 헤더 파일 노드 이름을 고유 ID로 사용합니다. 소스 트리에 심볼릭 링크 또는 NTFS 연결이 있거나 (생각보다 더 일반적으로) 다른 시스템 포함 디렉토리에 동일한 이름의 파일이있는 경우에도 실패 할 수 있습니다 (이것은 이전에 나에게 발생했습니다. 두 개의 다른 시스템 포함 경로에 설치된 동일한 라이브러리의 버전 1 및 버전 2). 결론 : 나는 나를 위해 컴파일러를 신뢰하기보다는 더 많은 제어권을 갖고 가끔 습식웨어 실수로 살기를 선호합니다.
Thomi


1

내 프로젝트 (VS 2008 SP1 사용)에서 다음 솔루션이 작동합니다.

헤더 파일 :

//myclass.h
#pragma once
#define _WINSOCKAPI_
#include <windows.h>

CPP 클래스 :

//myclass.cpp
#include "Util.h"
#include "winsock2class.h"
#pragma comment(lib, "Ws2_32.lib")

여기서 #include "winsock2class.h"는 winsock2.h를 구현 한 클래스를 의미합니다.

//winsock2class.h
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")

0

실제로 winsock2.h를 첫 번째 포함으로 정의 해야하는 문제가 발생했습니다. 다른 패키지의 포함과 관련된 다른 문제가있는 것 같습니다. 이것이 windows.h뿐만 아니라 모든 것을 포함하여 동일한 문제가 발생하는 사람에게 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.