해결되지 않은 외부 기호 __imp__fprintf 및 __imp____iob_func, SDL2


108

누군가가 무엇을 설명 할 수 있습니까?

__imp__fprintf

__imp____iob_func

해결되지 않은 외부 수단?

컴파일하려고 할 때 이러한 오류가 발생하기 때문입니다.

1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol __imp__fprintf referenced in function _ShowError
1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol __imp____iob_func referenced in function _ShowError
1>E:\Documents\Visual Studio 2015\Projects\SDL2_Test\Debug\SDL2_Test.exe : fatal error LNK1120: 2 unresolved externals

나는 이미 문제가 잘못된 연결로 인한 것이 아니라고 말할 수 있습니다. 모든 것을 올바르게 연결했지만 어떤 이유로 컴파일되지 않습니다.

SDL2를 사용하려고합니다.

Visual Studio 2015를 컴파일러로 사용하고 있습니다.

링커-> 입력-> 추가 종속성에서 SDL2.lib 및 SDL2main.lib에 연결했으며 VC ++ 디렉토리가 올바른지 확인했습니다.


1
링커 설정을 표시하여 증명해 주시겠습니까?
πάντα ῥεῖ

@ πάνταῥεῖ, 입력 링커 설정에서 SDL2.lib 및 SDL2main.lib에 연결했으며 디렉터리가 올바른 디렉터리를 가리키는 지 확인했습니다.
RockFrenzy

답변:


123

나는 이것이 왜 일어나고 있는지 마침내 알아 냈다!

Visual Studio 2015에서 stdin, stderr, stdout은 다음과 같이 정의됩니다.

#define stdin  (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))

그러나 이전에는 다음과 같이 정의되었습니다.

#define stdin  (&__iob_func()[0])
#define stdout (&__iob_func()[1])
#define stderr (&__iob_func()[2])

따라서 이제 __iob_func가 더 이상 정의되지 않아 이전 버전의 Visual Studio로 컴파일 된 .lib 파일을 사용할 때 링크 오류가 발생합니다.

이 문제를 해결하기 위해, 당신은 정의 시도 할 수 __iob_func()배열을 포함 반환해야하는 자신을 {*stdin,*stdout,*stderr}.

stdio 함수에 대한 다른 링크 오류 (제 경우에는 sprintf())와 관련 하여 legacy_stdio_definitions.lib 를 링커 옵션에 추가 할 수 있습니다.


1
추적 해 주셔서 감사합니다. IIRC {* stdin, * stdout, * stderr}의 문제점은 서로 다른 컴파일 단위에 stdin의 '자신의'복사본이있을 수 있다는 것입니다. 이것이 바로 이러한 함수가 호출 된 이유입니다.
Steven R. Loomis 2015

3
그것은 나에게도 해결되었습니다 extern "C". 선언 / 정의 에 사용하라는 알림 입니다.
Vargas

4
누군가 대체 함수가 어떻게 생겼는지 정확히 작성할 수 있습니까? 다른 변형을 시도했지만 컴파일 오류가 계속 발생합니다. 감사.
Milan Babuškov

55
extern "C" { FILE __iob_func[3] = { *stdin,*stdout,*stderr }; }
PoL0

1
위의 iob_func 정의가 작동하지 않습니다. 올바른 정의는 MarkH의 답변을 참조하십시오. (함수를 배열로 정의하고 호출이 작동 할 것으로 기대할 수는 없습니다.)
Hans Olsson

59

Milan Babuškov, IMO에게 이것은 대체 함수가 정확히 어떻게 생겼는지 :-)

FILE _iob[] = {*stdin, *stdout, *stderr};

extern "C" FILE * __cdecl __iob_func(void)
{
    return _iob;
}

5
MSVC 및 MSVC 버전 <2015에 대한 #ifdef가 누락되었습니다
paulm

1
MarkH는 정확 해 보이지만 작동하지 않는 다른 답변에서 메모합니다.
Hans Olsson

4
@paulm 당신이 의미하는 것 같아요 #if defined(_MSC_VER) && (_MSC_VER >= 1900).
Jesse Chisholm

@JesseChisholm은 아마도 이것이 MSVC의 알려진 모든 미래 버전에도 적용되는지 여부에 달려 있습니다.)
paulm

42

Microsoft는 이에 대한 특별 참고 사항을 가지고 있습니다 ( https://msdn.microsoft.com/en-us/library/bb531344.aspx#BK_CRT ) :

printf 및 scanf 계열의 함수는 이제 인라인으로 정의됩니다.

모든 printf 및 scanf 함수의 정의가 stdio.h , conio.h 및 기타 CRT 헤더 로 인라인으로 이동되었습니다 . 이는 적절한 CRT 헤더를 포함하지 않고 이러한 함수를 로컬로 선언 한 모든 프로그램에 대해 링커 오류 (LNK2019, 해결되지 않은 외부 기호)로 이어지는 주요 변경 사항입니다. 가능한 경우 CRT 헤더 (즉, #include 추가) 및 인라인 함수를 포함하도록 코드를 업데이트해야하지만 이러한 헤더 파일을 포함하도록 코드를 수정하지 않으려는 경우 대체 솔루션은 링커 입력, legacy_stdio_definitions.lib에 라이브러리 .

이 라이브러리를 IDE의 링커 입력에 추가하려면 프로젝트 노드의 컨텍스트 메뉴를 열고 속성을 선택한 다음 프로젝트 속성 대화 상자에서 링커를 선택하고 링커 입력을 편집하여 legacy_stdio_definitions.lib를 세미콜론에 추가합니다. -분리 된 목록.

프로젝트가 2015 년 이전의 Visual C ++ 릴리스로 컴파일 된 정적 라이브러리와 연결되는 경우 링커에서 확인되지 않은 외부 기호를보고 할 수 있습니다. 이러한 오류는 _iob , _iob_func에 대한 내부 stdio 정의 또는 __imp_ * 형식의 특정 stdio 함수에 대한 관련 가져 오기를 참조 할 수 있습니다.. 프로젝트를 업그레이드 할 때 최신 버전의 Visual C ++ 컴파일러 및 라이브러리를 사용하여 모든 정적 라이브러리를 다시 컴파일하는 것이 좋습니다. 라이브러리가 소스를 사용할 수없는 타사 라이브러리 인 경우 타사에 업데이트 된 바이너리를 요청하거나 해당 라이브러리의 사용을 이전 버전의 Visual C ++ 컴파일러로 컴파일하는 별도의 DLL로 캡슐화해야합니다. 및 도서관.


7
또는 #pragma comment(lib, "legacy_stdio_definitions.lib")-그러나 이것은 수정되지 않습니다-이것에 __imp___iob_func대한 레거시 lib도 있습니까?
bytecode77

29

위에서 대답했듯이 정답은 VS2015로 모든 것을 컴파일하는 것이지만 관심을 위해 다음은 문제에 대한 분석입니다.

이 기호는 Microsoft에서 VS2015의 일부로 제공하는 정적 라이브러리에 정의되어 있지 않은 것으로 보이며, 다른 모든 항목이 그렇기 때문에 다소 특이합니다. 그 이유를 알아 보려면 해당 함수의 선언과 더 중요한 것은 어떻게 사용되는지 살펴 봐야합니다.

다음은 Visual Studio 2008 헤더의 스 니펫입니다.

_CRTIMP FILE * __cdecl __iob_func(void);
#define stdin (&__iob_func()[0])
#define stdout (&__iob_func()[1])
#define stderr (&__iob_func()[2])

따라서 함수의 작업은 FILE 객체 배열의 시작을 반환하는 것임을 알 수 있습니다 (핸들이 아니라 "FILE *"이 핸들이고 FILE이 중요한 상태를 저장하는 기본 불투명 데이터 구조 임). 이 함수의 사용자는 다양한 fscanf, fprintf 스타일 호출에 사용되는 세 가지 매크로 stdin, stdout 및 stderr입니다.

이제 Visual Studio 2015에서 동일한 사항을 정의하는 방법을 살펴 보겠습니다.

_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
#define stdin (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))

따라서 대체 함수가 파일 객체 배열의 주소가 아닌 파일 핸들을 반환하도록 접근 방식이 변경되었으며 매크로는 단순히 식별 번호를 전달하는 함수를 호출하도록 변경되었습니다.

그렇다면 왜 그들은 호환 가능한 API를 제공 할 수 없습니까? __iob_func를 통한 원래 구현 측면에서 Microsoft가 위반할 수없는 두 가지 주요 규칙이 있습니다.

  1. 이전과 동일한 방식으로 인덱싱 할 수있는 세 개의 FILE 구조 배열이 있어야합니다.
  2. FILE의 구조적 레이아웃은 변경할 수 없습니다.

위의 내용 중 하나가 변경되면 해당 API가 호출 될 경우 연결된 기존 컴파일 된 코드가 심하게 잘못 될 수 있습니다.

FILE이 어떻게 정의되었는지 살펴 보겠습니다.

먼저 VS2008 FILE 정의 :

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
        };
typedef struct _iobuf FILE;

이제 VS2015 FILE 정의 :

typedef struct _iobuf
{
    void* _Placeholder;
} FILE;

그래서 그것의 핵심은 구조가 변화했습니다. __iob_func를 참조하는 기존의 컴파일 된 코드는 반환 된 데이터가 인덱싱 할 수있는 배열이고 해당 배열에서 요소가 같은 거리 떨어져 있다는 사실에 의존합니다.

위의 답변에서 언급 된 가능한 솔루션은 다음과 같은 몇 가지 이유로 작동하지 않습니다 (호출 된 경우).

FILE _iob[] = {*stdin, *stdout, *stderr};

extern "C" FILE * __cdecl __iob_func(void)
{
    return _iob;
}

FILE 배열 _iob는 VS2015로 컴파일되므로 void *를 포함하는 구조 블록으로 배치됩니다. 32 비트 정렬을 가정하면 이러한 요소는 4 바이트 떨어져 있습니다. 따라서 _iob [0]은 오프셋 0, _iob [1]은 오프셋 4, _iob [2]는 오프셋 8에 있습니다. 대신 호출 코드는 FILE이 훨씬 더 길고 시스템에서 32 바이트로 정렬 될 것으로 예상합니다. 반환 된 배열의 주소를 가져와 0 바이트를 추가하여 요소 0 (괜찮음)에 도달하지만 _iob [1]의 경우 32 바이트를 추가해야한다고 추론하고 _iob [2]에 대해서는 추론합니다. 64 바이트를 추가해야한다는 것입니다 (VS2008 헤더에서보기 때문에). 그리고 실제로 VS2008의 디스 어셈블 된 코드는 이것을 보여줍니다.

위 솔루션의 두 번째 문제 는 FILE * 핸들이 아니라 FILE 구조 (* stdin)의 내용을 복사 한다는 것 입니다. 따라서 모든 VS2008 코드는 VS2015와 다른 기본 구조를 보게됩니다. 구조에 포인터 만 포함 된 경우 작동 할 수 있지만 큰 위험입니다. 어쨌든 첫 번째 문제는 이것을 무의미하게 만듭니다.

내가 꿈꿀 수 있었던 유일한 해킹은 __iob_func가 호출 스택을 통해 그들이 찾고있는 실제 파일 핸들 (반환 된 주소에 추가 된 오프셋을 기반으로)을 알아 내고 다음과 같은 계산 된 값을 반환하는 것입니다. 정답을 제공합니다. 이것은 들리는 것만 큼 미쳤지 만 x86 전용 프로토 타입 (x64가 아님)은 아래에 나열되어 있습니다. 내 실험에서는 제대로 작동했지만 마일리지가 다를 수 있습니다. 프로덕션 용도로는 권장되지 않습니다!

#include <windows.h>
#include <stdio.h>
#include <dbghelp.h>

/* #define LOG */

#if defined(_M_IX86)

#define GET_CURRENT_CONTEXT(c, contextFlags) \
  do { \
    c.ContextFlags = contextFlags; \
    __asm    call x \
    __asm x: pop eax \
    __asm    mov c.Eip, eax \
    __asm    mov c.Ebp, ebp \
    __asm    mov c.Esp, esp \
  } while(0);

#else

/* This should work for 64-bit apps, but doesn't */
#define GET_CURRENT_CONTEXT(c, contextFlags) \
  do { \
    c.ContextFlags = contextFlags; \
    RtlCaptureContext(&c); \
} while(0);

#endif

FILE * __cdecl __iob_func(void)
{
    CONTEXT c = { 0 };
    STACKFRAME64 s = { 0 };
    DWORD imageType;
    HANDLE hThread = GetCurrentThread();
    HANDLE hProcess = GetCurrentProcess();

    GET_CURRENT_CONTEXT(c, CONTEXT_FULL);

#ifdef _M_IX86
    imageType = IMAGE_FILE_MACHINE_I386;
    s.AddrPC.Offset = c.Eip;
    s.AddrPC.Mode = AddrModeFlat;
    s.AddrFrame.Offset = c.Ebp;
    s.AddrFrame.Mode = AddrModeFlat;
    s.AddrStack.Offset = c.Esp;
    s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
    imageType = IMAGE_FILE_MACHINE_AMD64;
    s.AddrPC.Offset = c.Rip;
    s.AddrPC.Mode = AddrModeFlat;
    s.AddrFrame.Offset = c.Rsp;
    s.AddrFrame.Mode = AddrModeFlat;
    s.AddrStack.Offset = c.Rsp;
    s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
    imageType = IMAGE_FILE_MACHINE_IA64;
    s.AddrPC.Offset = c.StIIP;
    s.AddrPC.Mode = AddrModeFlat;
    s.AddrFrame.Offset = c.IntSp;
    s.AddrFrame.Mode = AddrModeFlat;
    s.AddrBStore.Offset = c.RsBSP;
    s.AddrBStore.Mode = AddrModeFlat;
    s.AddrStack.Offset = c.IntSp;
    s.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif

    if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
    {
#ifdef LOG
        printf("Error: 0x%08X (Address: %p)\n", GetLastError(), (LPVOID)s.AddrPC.Offset);
#endif
        return NULL;
    }

    if (s.AddrReturn.Offset == 0)
    {
        return NULL;
    }

    {
        unsigned char const * assembly = (unsigned char const *)(s.AddrReturn.Offset);
#ifdef LOG
        printf("Code bytes proceeding call to __iob_func: %p: %02X,%02X,%02X\n", assembly, *assembly, *(assembly + 1), *(assembly + 2));
#endif
        if (*assembly == 0x83 && *(assembly + 1) == 0xC0 && (*(assembly + 2) == 0x20 || *(assembly + 2) == 0x40))
        {
            if (*(assembly + 2) == 32)
            {
                return (FILE*)((unsigned char *)stdout - 32);
            }
            if (*(assembly + 2) == 64)
            {
                return (FILE*)((unsigned char *)stderr - 64);
            }

        }
        else
        {
            return stdin;
        }
    }
    return NULL;
}

정답은 이것이 하나이며, 가장 쉬운 수정은 프로젝트를 VS2015로 업그레이드 한 다음 컴파일하는 것입니다.
Akumaburn

2
제 경우에는 Visual Studio 2015 업데이트 3을 사용하기 위해 Visual Studio 2013에서 많은 프로젝트 (C ++ 및 C # 프로젝트)를 업그레이드해야합니다. C ++ 프로젝트를 빌드 할 때 VC100 (Visual Studio 2010 C ++ 컴파일러)을 유지하고 싶지만 동일한 오류가 발생합니다. 위와 같이. 링커에 legacy_stdio_definitions.lib 를 추가하여 imp _fprintf 를 수정했습니다 . _imp____iob_func 도 어떻게 고칠 수 있습니까?
Mohamed BOUZIDI

이전 질문에 대답하기 전에 msbuild 14 및 IntelCompiler 2016 및 VC100을 사용하여 C ++ 프로젝트를 컴파일 할 때 이러한 오류가 발생하는 것이 정상입니까?
Mohamed BOUZIDI

1
x64 컴파일을 위해 무엇을 할 수 있습니까?
athos

28

VS2015에서 동일한 문제가 발생했습니다. VS2015에서 SDL2 소스를 컴파일하여 해결했습니다.

  1. http://libsdl.org/download-2.0.php로 이동하여 SDL 2 소스 코드를 다운로드합니다.
  2. VS2015에서 SDL_VS2013.sln을 엽니 다 . 프로젝트를 변환하라는 메시지가 표시됩니다. 해.
  3. SDL2 프로젝트를 컴파일합니다.
  4. SDL2main 프로젝트를 컴파일합니다.
  5. VS2015의 SDL 2 프로젝트에서 새로 생성 된 출력 파일 SDL2main.lib, SDL2.lib 및 SDL2.dll을 사용합니다.

4
BTW, SDL 2.0.3을 빌드하려면 2010 년 6 월 DirectX SDK를 설치해야합니다.
Joe

1
나를 위해 일했습니다, 감사합니다 !! 하지만 컴파일 SDL2main하고 복사 SDL2main.lib
만하면 됐습니다

10

이유는 모르겠지만 :

#ifdef main
#undef main
#endif

포함 후 그러나 메인이 내 경험에서 수정하기 전에.


1
.... 좋아 .... 그래서 이걸 시도하기 전에 나는 이것이 어떻게 든 효과가 있을지 의심 스럽지만 완전히 효과가 있다고 스스로에게 말했다 ..이게 왜 효과가 있는지 설명 해줄 수 있니 ...?
트레버 하트

1
@TrevorHart 나는 그것이 "정의되지 않은"버퍼에 대한 "결함이있는"SDL 메인 포함 참조를 정의 해제 한다고 믿으며 , 당신의 버퍼가 당신의 버퍼를 사용한다면, 그것은 모두 잘 작동한다.
XGood

2
이것은 끔찍한 나쁜 연습 해킹이지만 3 줄이고 작동하며 SDL을 구축하는 데 토끼 구멍을 뚫지 않아도되었습니다. 잘했습니다.
Cheezmeister

1
@Cheezmeister 나쁜 연습과 해킹은 종종 모든 것에 필요합니다. 특히 필요하지 않은 것들.
XGood


7

연결한다는 것은 제대로 작동하지 않는다는 것을 의미합니다. VS2012 및 VS2015의 stdio.h를 파면 다음이 저에게 효과적이었습니다. 아아, {stdin, stdout, stderr} 중 하나에 대해 작동할지 여부를 결정해야합니다.

extern "C" FILE* __cdecl __iob_func()
{
    struct _iobuf_VS2012 { // ...\Microsoft Visual Studio 11.0\VC\include\stdio.h #56
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname; };
    // VS2015 has only FILE = struct {void*}

    int const count = sizeof(_iobuf_VS2012) / sizeof(FILE);

    //// stdout
    //return (FILE*)(&(__acrt_iob_func(1)->_Placeholder) - count);

    // stderr
    return (FILE*)(&(__acrt_iob_func(2)->_Placeholder) - 2 * count);
}

7

내 조언은 __iob_func를 구현하지 않는 것입니다.

이러한 오류를 수정하는 동안 :

libpngd.v110.lib(pngrutil.obj) : error LNK2001: unresolved external symbol ___iob_func curllib.v110.lib(mprintf.obj) : error LNK2001: unresolved external symbol ___iob_func

다른 답변의 솔루션을 시도했지만 결국 FILE*C 배열을 반환하는 것은 Windows의 내부 IOB 구조체 배열과 일치하지 않습니다. @Volker는 stdin, stdout또는 중 하나 이상에서 작동하지 않는다는 것이 옳습니다 stderr.

라이브러리가 실제로 이러한 스트림 중 하나를 사용 하면 충돌 합니다. 당신의 프로그램이 lib가 그것들을 사용하도록하지 않는 한, 당신은 결코 알 수 없을 것 입니다. 예를 들어 CRC가 PNG의 메타 데이터에서 일치하지 않을 때 png_default_error씁니다 stderr. (일반적으로 충돌 할 가치가있는 문제가 아님)

결론 : stdin, stdout 및 / 또는 stderr을 사용하는 경우 VS2012 (Platform Toolset v110 / v110_xp) 및 VS2015 + 라이브러리를 혼합 할 수 없습니다.

해결 방법 : __iob_func현재 버전의 VS 및 일치하는 플랫폼 도구 집합으로 해결되지 않은 기호 가있는 라이브러리를 다시 컴파일하십시오 .



2

다음 기능으로이 문제를 해결합니다. Visual Studio 2019를 사용합니다.

FILE* __cdecl __iob_func(void)
{
    FILE _iob[] = { *stdin, *stdout, *stderr };
    return _iob;
}

stdin 매크로 정의 함수 호출이므로 "* stdin"표현식은 전역 배열 이니셜 라이저를 사용할 수 없습니다. 그러나 로컬 어레이 초기자가 가능합니다. 미안 해요, 저는 영어를 잘 못합니다.


1

위의 트릭이 작동하지 않는 답변을 찾고있는 사람을 위해. 정적 연결은이 문제를 해결하는 방법입니다. 아래와 같이 런타임 라이브러리 설정을 변경하십시오.

Project properties --> C/C++ --> Code generation --> Runtime Library --> Multi-threaded Debug (/MTd) instead of /MDd


이 솔루션에 대한 토론은 다음과 같습니다. social.msdn.microsoft.com/Forums/vstudio/en-US/…
Sisir

0

나는 문제를 해결할 수 있었다.

오류의 원인은 SDLmain 소스 코드에서 찾을 수있는이 코드 줄입니다.

fprintf(stderr, "%s: %s\n", title, message);

그래서 내가 한 일은 그 줄의 SDLmain에서 소스 코드를 편집하는 것입니다.

fprintf("%s: %s\n", title, message);

그런 다음 SDLmain을 빌드하고 SDL2 라이브러리 디렉토리의 이전 SDLmain.lib를 새로 빌드하고 편집 한 것으로 복사하고 교체했습니다.

그런 다음 SDL2로 프로그램을 실행했을 때 오류 메시지가 나타나지 않고 코드가 원활하게 실행되었습니다.

이것이 나중에 나를 물릴 지 모르겠지만 모든 것이 잘 진행되고 있습니다.


변경 사항은 그 자체로 실수이며 질문에 설명 된 문제를 해결하지 못했을 것입니다. 더 이상 링커 오류가 발생하지 않는 것은 우연 일 뿐이며 이는 아마도 라이브러리를 다시 빌드 한 결과 일 것입니다.
Ross Ridge

@RossRidge, 오 예, 그럴 수도 있습니다. 아 글쎄.
RockFrenzy

0

이는 msvcr10.dll (또는 이와 유사한) 대신 msvcrt.dll에 연결할 때 발생할 수 있으며 이는 좋은 계획입니다. 최종 소프트웨어 패키지 내에서 Visual Studio의 런타임 라이브러리를 재배포 할 수 있기 때문입니다.

이 해결 방법은 (Visual Studio 2008에서) 도움이됩니다.

#if _MSC_VER >= 1400
#undef stdin
#undef stdout
#undef stderr
extern "C" _CRTIMP extern FILE _iob[];
#define stdin   _iob
#define stdout  (_iob+1)
#define stderr  (_iob+2)
#endif

이 코드 조각은 Visual Studio 6 및 해당 컴파일러에 필요하지 않습니다. 따라서 #ifdef.


0

이 이미 풍부한 스레드에서 더 많은 혼란을 가져 오기 위해 fprintf에서 동일한 해결되지 않은 외부에서 충돌했습니다.

main.obj : error LNK2019: unresolved external symbol __imp__fprintf referenced in function _GenerateInfoFile

내 경우에는 Visual Studio 2005 (Visual Studio 8.0)에서 다소 다른 컨텍스트에 있었지만 제 3자가 아닌 내 코드에서 오류가 발생했습니다 (내가 컴파일 할 때와 동일한 코드).

이 오류는 내 컴파일러 플래그의 / MD 옵션에 의해 트리거되었습니다. / MT로 전환하면 문제가 제거되었습니다. 일반적으로 정적으로 연결 (MT)하면 동적 (MD)보다 문제가 더 많이 발생하기 때문에 이상하지만 다른 서비스를 제공하는 경우에만 거기에 넣습니다.


0

필자의 경우이 오류는 MSVC 버전 종속 런타임 라이브러리 DLL (msvcr10.dll 등)에 대한 종속성을 제거하거나 정적 런타임 라이브러리도 제거하여 실행 파일에서 과도한 지방을 제거하려는 시도에서 발생합니다.

그래서 나는 / NODEFAULTLIB 링커 스위치, 내 스스로 만든 "msvcrt-light.lib"(필요할 때 구글), 그리고 mainCRTStartup()/ WinMainCRTStartup()엔트리를 사용한다.

Visual Studio 2015 이후 IMHO이므로 이전 컴파일러를 고수했습니다.

그러나 _NO_CRT_STDIO_INLINE 기호를 정의 하면 모든 번거 로움이 제거되고 간단한 "Hello World"응용 프로그램은 다시 3KB 크기가 작고 비정상적인 DLL에 의존하지 않습니다. Visual Studio 2017에서 테스트되었습니다.


-2

이 코드를 소스 파일에 붙여넣고 다시 빌드하십시오. 나를 위해 일했다!

#include stdio.h

파일 _iob [3];

파일 * __cdecl __iob_func (void) {

_iob [0] = * stdin;

_iob [0] = * stdout;

_iob [0] = * stderr;

return _iob;

}


```와 몇 가지 설명으로
포맷을

이 코드가 문제를 해결할 수 있지만 문제를 해결하는 방법과 이유에 대한 설명포함 하여 게시물의 품질을 향상시키는 데 실제로 도움이되며 더 많은 찬성 투표가 발생할 수 있습니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Brian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.