अनसुलझे बाहरी प्रतीक __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 का उपयोग करने की कोशिश कर रहा हूं।

मैं विजुअल स्टूडियो 2015 को कंपाइलर के रूप में उपयोग कर रहा हूं।

मैं लिंकर में SDL2.lib और SDL2main.lib से जुड़ा हूं -> इनपुट -> अतिरिक्त निर्भरताएं और मैंने यह सुनिश्चित किया है कि VC ++ निर्देशिकाएँ सही हैं।


1
क्या आप अपने लिंकर की सेटिंग्स दिखा कर कृपया उसे प्रूव कर सकते हैं।
atν 13:α τ

@ Lν2αῥεῖ, मैंने SDL2.lib और SDL2main.lib को इनपुट लिंकर सेटिंग्स में जोड़ा है और मैंने सुनिश्चित किया है कि निर्देशिका सही निर्देशिका की ओर इशारा कर रही हैं।
रॉकफ्रेम

जवाबों:


123

मैंने आखिर पता लगा लिया कि ऐसा क्यों हो रहा है!

दृश्य स्टूडियो 2015 में, स्टडिन, स्टैडर, स्टडआउट को निम्नानुसार परिभाषित किया गया है:

#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 को अब परिभाषित नहीं किया जाता है जो दृश्य स्टूडियो के पिछले संस्करणों के साथ संकलित .lib फ़ाइल का उपयोग करते समय लिंक त्रुटि की ओर जाता है।

समस्या को हल करने के लिए, आप __iob_func()अपने आप को परिभाषित करने की कोशिश कर सकते हैं जिसमें एक सरणी युक्त होना चाहिए {*stdin,*stdout,*stderr}

Stdio फ़ंक्शन (मेरे मामले में यह था sprintf()) के बारे में अन्य लिंक त्रुटियों के बारे में , आप अपने linker विकल्पों में legacy_stdio_definitions.lib जोड़ सकते हैं ।


1
इसे नीचे ट्रैक करने के लिए धन्यवाद। IIRC को {* stdin, * stdout, * stderr} के साथ समस्या यह हो सकती है कि विभिन्न संकलन इकाइयों में स्टडिन की अपनी 'प्रति' हो सकती है, यही कारण है कि इन कार्यों को सीधे कहा जाता था।
स्टीवन आर। लूमिस

3
मेरे लिए भी हल है, बस extern "C"घोषणा / परिभाषा में उपयोग करने के लिए एक अनुस्मारक ।
वरगास

4
क्या कोई ठीक से लिख सकता है कि प्रतिस्थापन कार्य कैसा दिखना चाहिए? मैंने अलग-अलग वेरिएंट आज़माए और मुझे कंपाइल एरर मिलते रहे। धन्यवाद।
मिलन बाबुकोव 17

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

1
ऊपर iob_func परिभाषा काम नहीं करती है, सही परिभाषा के लिए MarkH का उत्तर देखें। (आप एक समारोह को एक सरणी के रूप में परिभाषित नहीं कर सकते हैं और काम करने के लिए कॉल की उम्मीद कर सकते हैं।)
हंस ओल्सन

59

मिलान बाबूचकोव, आईएमओ के लिए, यह वही है जो प्रतिस्थापन फ़ंक्शन को :-) जैसा दिखना चाहिए

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

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

5
बस MSVC के लिए और MSVC संस्करण <2015 के लिए एक
#ifdef गायब है

1
जैसा कि MarkH एक अन्य उत्तर में नोट करता है जो सही दिखता है, लेकिन काम नहीं करेगा।
हंस ओल्सन

4
@ अंपुलम मुझे लगता है कि आपका मतलब है #if defined(_MSC_VER) && (_MSC_VER >= 1900)
जेसी चिशोल्म

@JesseChisholm शायद, यह निर्भर करता है कि यह MSVC के हर ज्ञात संस्करण पर लागू होता है या नहीं;)
paulm

42

इस पर Microsoft का एक विशेष ध्यान है ( https://msdn.microsoft.com/en-us/library/bb531344.aspx#BK_CRT ):

फ़ंक्शंस के प्रिंटफ़ और स्कैनफ़ परिवार अब इनलाइन परिभाषित किए गए हैं।

सभी प्रिंटफ और स्कैनफ फ़ंक्शंस की परिभाषाएँ इनलाइन को stdio.h , conio.h और अन्य CRT हेडर में स्थानांतरित कर दिया गया है । यह एक ब्रेकिंग परिवर्तन है जो किसी भी प्रोग्राम के लिए एक लिंकर त्रुटि (LNK2019, अनसुलझे बाहरी प्रतीक) की ओर जाता है जो उचित सीआरटी हेडर को शामिल किए बिना इन कार्यों को स्थानीय रूप से घोषित करता है। यदि संभव हो तो, आपको CRT हेडर (यानी #include जोड़ें) और इनलाइन फ़ंक्शन को शामिल करने के लिए कोड को अपडेट करना चाहिए, लेकिन यदि आप इन हेडर फ़ाइलों को शामिल करने के लिए अपने कोड को संशोधित नहीं करना चाहते हैं, तो एक अतिरिक्त समाधान एक अतिरिक्त जोड़ना है अपने लिंकर इनपुट के लिए लाइब्रेरी, legacy_stdio_definitions.lib

IDE में अपने लिंकर इनपुट में इस लाइब्रेरी को जोड़ने के लिए, प्रोजेक्ट नोड के लिए संदर्भ मेनू खोलें, गुण चुनें, फिर प्रोजेक्ट गुण संवाद बॉक्स में, Linker चुनें, और legacy_stdio_definitions.lib को अर्ध-उपनिवेश में जोड़ने के लिए लिंकर इनपुट संपादित करें -सूचित सूची

यदि आपका प्रोजेक्ट स्थैतिक पुस्तकालयों के साथ लिंक करता है जो 2015 से पहले विजुअल C ++ की रिलीज के साथ संकलित किया गया था, तो लिंकर एक अनसुलझे बाहरी प्रतीक की रिपोर्ट कर सकता है। ये त्रुटियां _iob , _iob_func , या __imp_ * के रूप में कुछ stdio फ़ंक्शंस के लिए संबंधित आयातों के लिए आंतरिक stdio परिभाषाओं को संदर्भित कर सकती हैं । Microsoft अनुशंसा करता है कि जब आप किसी प्रोजेक्ट को अपग्रेड करते हैं, तो आप Visual C ++ कंपाइलर और लाइब्रेरीज़ के नवीनतम संस्करण के साथ सभी स्टैटिक लाइब्रेरीज़ को फिर से जोड़ दें। यदि लाइब्रेरी एक तृतीय-पक्ष लाइब्रेरी है, जिसके लिए स्रोत उपलब्ध नहीं है, तो आपको या तो तीसरे पक्ष से एक अद्यतन बाइनरी का अनुरोध करना चाहिए या उस लाइब्रेरी के अपने उपयोग को एक अलग DLL में एन्क्रिप्ट करना चाहिए, जिसे आप Visual C ++ कंपाइलर के पुराने संस्करण के साथ संकलित करते हैं और पुस्तकालय।


7
या #pragma comment(lib, "legacy_stdio_definitions.lib")- लेकिन यह ठीक नहीं करता है __imp___iob_func- क्या इसके लिए भी कोई विरासत है?
bytecode77

29

जैसा कि ऊपर बताया गया है, सही उत्तर सब कुछ VS2015 के साथ संकलित करना है, लेकिन ब्याज के लिए निम्नलिखित समस्या का मेरा विश्लेषण है।

यह प्रतीक Microsoft द्वारा VS2015 के भाग के रूप में प्रदान की गई किसी भी स्थिर लाइब्रेरी में परिभाषित नहीं किया गया है, जो कि अन्य लोगों के मुकाबले अजीबोगरीब है। क्यों की खोज करने के लिए, हमें उस फ़ंक्शन की घोषणा को देखने की आवश्यकता है और, इससे भी महत्वपूर्ण बात यह है कि इसका उपयोग कैसे किया जाता है।

यहाँ दृश्य स्टूडियो 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 स्टाइल कॉल के लिए उपयोग किए जाते हैं।

अब आइए नजर डालते हैं कि विजुअल स्टूडियो 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 क्यों नहीं दे सकते? दो प्रमुख नियम हैं जो Microsoft __iob_func के माध्यम से अपने मूल कार्यान्वयन के संदर्भ में उल्लंघन नहीं कर सकते हैं:

  1. तीन फ़ाइल संरचनाओं की एक सरणी होनी चाहिए जिसे पहले की तरह ही अनुक्रमित किया जा सकता है।
  2. FILE का संरचनात्मक लेआउट नहीं बदल सकता है।

उपरोक्त में से किसी में भी बदलाव का मतलब मौजूदा संकलित कोड से जुड़ा होगा, जो कि एपीआई कहलाता है तो बुरी तरह से गलत हो जाएगा।

आइए नजर डालते हैं कि FILE को कैसे परिभाषित किया गया है।

पहली VS2008 फ़ाइल परिभाषा:

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

और अब VS2015 फ़ाइल परिभाषा:

typedef struct _iobuf
{
    void* _Placeholder;
} FILE;

तो इसका क्रुक्स है: संरचना ने आकार बदल दिया है। मौजूदा संकलित कोड __iob_func का संदर्भ देते हुए इस तथ्य पर निर्भर करता है कि लौटाया गया डेटा दोनों एक सरणी है जिसे अनुक्रमित किया जा सकता है और उस सरणी में तत्व समान दूरी पर हैं।

इन रेखाओं के साथ ऊपर दिए गए उत्तर में वर्णित संभावित समाधान कुछ कारणों से काम नहीं करेंगे (यदि कहा जाता है):

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

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

फ़ाइल सरणी _iob को VS2015 के साथ संकलित किया जाएगा और इसलिए इसे एक शून्य * संरचना वाले ब्लॉक के रूप में रखा जाएगा। 32-बिट संरेखण मानते हुए, ये तत्व 4 बाइट्स के अलावा होंगे। तो _iob [0] ऑफ़सेट 0 पर है, _iob [1] ऑफसेट 4 पर है और _iob [2] ऑफ़सेट 8 पर है। कॉलिंग कोड इसके बजाय FILE के अधिक लंबे समय तक बने रहने की उम्मीद करेगा, मेरे सिस्टम पर 32 बाइट्स में संरेखित है, और इसी तरह यह दिए गए ऐरे का पता लेगा और शून्य तत्व को प्राप्त करने के लिए 0 बाइट्स जोड़ देगा (जो कि ठीक है), लेकिन _iob [1] के लिए यह कटौती करेगा कि उसे 32 बाइट्स जोड़ने की जरूरत है और _iob [2] के लिए यह कटौती करेगा यह 64-बाइट्स जोड़ने की जरूरत है (क्योंकि यह कैसे VS2008 हेडर में देखा गया है)। और वास्तव में VS2008 के लिए असंतुष्ट कोड इसे प्रदर्शित करता है।

उपरोक्त समाधान के साथ एक द्वितीयक समस्या यह है कि यह FILE संरचना की सामग्री की प्रतिलिपि बनाता है (* stdin), न कि FILE * हैंडल। इसलिए कोई भी 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;
}

सही उत्तर यह एक है, सबसे आसान फिक्स है जैसा कि प्रोजेक्ट को वीएस २०१५ में अपग्रेड करने और फिर संकलन करने के लिए कहा गया है।
अकामुबर्न

2
मेरे मामले में, मुझे विजुअल स्टूडियो 2015 अपडेट 3 का उपयोग करने के लिए विजुअल स्टूडियो 2013 से कई परियोजनाओं (C ++ और C # प्रोजेक्ट्स) को अपग्रेड करने की आवश्यकता है। मैं C ++ प्रोजेक्ट्स का निर्माण करते समय VC100 (विजुअल स्टूडियो 2010 C ++ कंपाइलर) रखना चाहता हूं, लेकिन मेरे पास समान त्रुटियां हैं ऊपरोक्त अनुसार। मैं तय इम्प _fprintf जोड़कर legacy_stdio_definitions.lib लिंकर करने के लिए। मैं कैसे भी ठीक कर सकता हूँ _imp____iob_func ?
मोहम्मद बूजिदी

मेरे पिछले प्रश्न का उत्तर देने से पहले, क्या यह सामान्य है कि C ++ परियोजनाओं को संकलित करने के लिए msbuild 14 और IntelCompiler 2016 और VC100 का उपयोग करते समय ये त्रुटियां होती हैं?
मोहम्मद बूजिदी

1
मैं x64 संकलन के लिए क्या कर सकता हूं?
एथोस

28

VS2015 में मेरा भी यही मुद्दा था। मैंने इसे VS2015 में SDL2 स्रोतों को संकलित करके हल किया है।

  1. Http://libsdl.org/download-2.0.php पर जाएं और एसडीएल 2 सोर्स कोड डाउनलोड करें।
  2. VS2015 में SDL_VS2013.sl खोलें । आपको परियोजनाओं को परिवर्तित करने के लिए कहा जाएगा। कर दो।
  3. SDL2 प्रोजेक्ट संकलित करें।
  4. संकलन SDL2main प्रोजेक्ट।
  5. VS2015 में अपने SDL 2 प्रोजेक्ट में नई उत्पन्न आउटपुट फाइल SDL2main.lib, SDL2.lib और SDL2.dll का उपयोग करें।

4
BTW, SDL 2.0.3 के निर्माण के लिए जून 2010 डायरेक्टएक्स SDK की आवश्यकता है।
जो

1
मेरे लिए काम किया, धन्यवाद !! लेकिन मैं केवल संकलन करने के लिए आवश्यक SDL2mainहै और पर कॉपीSDL2main.lib
kgwong

10

मुझे पता नहीं क्यों लेकिन:

#ifdef main
#undef main
#endif

शामिल करने के बाद लेकिन इससे पहले कि आपके मुख्य को इसे मेरे अनुभव से ठीक करना चाहिए।


1
.... ठीक है .... इसलिए यह प्रयास करने से पहले मैंने खुद से कहा कि मुझे किसी तरह संदेह है कि यह काम करने वाला है फिर भी यह पूरी तरह से किया है ..... क्या आप बता सकते हैं कि यह क्यों काम करता है ...?
ट्रेवर हार्ट

1
@TrevorHart मेरा मानना ​​है कि यह "दोषपूर्ण" एसडीएल मुख्य को "अपरिभाषित" बफ़र्स के संदर्भ में शामिल करता है और यदि आप अपने बफ़र्स का उपयोग करते हैं, तो यह सभी अच्छे और अच्छे काम करता है।
XGood

2
यह भयानक बुरा अभ्यास हैक्स है, लेकिन यह 3 लाइनें है और यह काम करता है और इसने मुझे SDL के निर्माण में rabbithole होने से बचाया ... इसलिए अच्छी तरह से किया गया।
Cheezmeister

1
@Cheezmeister खराब अभ्यास और हैक अक्सर सब कुछ के लिए आवश्यक हैं। खासतौर पर वे चीजें जिनकी उन्हें जरूरत नहीं होनी चाहिए।
XGood

8

इस समस्या का एक और हालिया समाधान: अधिक हाल के sdl libs का उपयोग करें

" https://buildbot.libsdl.org/sdl-builds/sdl-visualstudio/?C=M=O=D "

उन्हें लगता है कि समस्या ठीक हो गई है, हालांकि यह केवल 32 बिट लाइब्रेरी है (मुझे लगता है)।


7

लिंक करने का मतलब है ठीक से काम न करना। VS2012 और VS2015 की stdio.h में खुदाई करना मेरे लिए निम्न काम किया। काश, आपको यह तय करना होगा कि यह {स्टड, स्टडआउट, स्टडर} में से एक के लिए काम करना चाहिए, कभी भी एक से अधिक नहीं।

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*सी-सरणी लौटना विंडोज के आंतरिक आईओबी संरचनाओं के एक सरणी के साथ मेल नहीं खाता। @ वोल्कर सही है कि यह कभी भी एक से अधिक के लिए काम नहीं करेगा stdin, stdoutया stderr

यदि एक पुस्तकालय वास्तव में उन धाराओं में से एक का उपयोग करता है, तो यह दुर्घटनाग्रस्त हो जाएगा । जब तक आपके कार्यक्रम का उपयोग करने के लिए उन्हें देय नहीं होता है, तो आप कभी नहीं जान पाएंगे । उदाहरण के लिए, png_default_errorलिखते हैं कि stderrकब PNG के मेटाडेटा में CRC मेल नहीं खाता है। (आम तौर पर दुर्घटना-योग्य मुद्दा नहीं)

निष्कर्ष: VS2012 (प्लेटफ़ॉर्म टूलसेट v110 / v110_xp) और VS2015 + लाइब्रेरीज़ को मिक्स करना संभव नहीं है, अगर वे स्टड, स्टैडआउट और / या स्टैडर का उपयोग करते हैं।

समाधान: अपने लाइब्रेरियों को पुनःप्रकाशित करें, __iob_funcजिसमें आपके मौजूदा संस्करण VS और एक मेलिंग प्लेटफ़ॉर्म टूलसेट के साथ अनसुलझे प्रतीक हैं।



2

मैं निम्नलिखित समस्या के साथ इस समस्या को हल करता हूं। मैं विजुअल स्टूडियो 2019 का उपयोग करता हूं।

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

क्योंकि स्टड मैक्रो परिभाषित फ़ंक्शन कॉल करता है, "* स्टडिन" अभिव्यक्ति का उपयोग वैश्विक सरणी आरंभीकरणकर्ता नहीं कर सकता। लेकिन स्थानीय सरणी शुरुआती संभव है। क्षमा करें, मैं अंग्रेजी में गरीब हूं।


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 के साथ चलाया तो कोई त्रुटि संदेश नहीं आया और कोड आसानी से चला।

मुझे नहीं पता कि यह बाद में मुझे काटेगा, लेकिन इसलिए सब कुछ बहुत अच्छा चल रहा है।


आपका परिवर्तन अपने आप में एक गलती है और आपके प्रश्न में वर्णित समस्या को ठीक नहीं करेगा। यह केवल एक संयोग है कि अब आपको लिंकर की त्रुटियां नहीं हो रही हैं, जो संभवत: पूरी तरह से परिणाम है कि आपने लाइब्रेरी का पुनर्निर्माण कैसे किया।
रॉस रिज

@RossRidge, ओह हाँ, जो अभी हो सकता है। ठीक है।
रॉकफ्रेम

0

यह तब हो सकता है जब आप msvcr10.dll (या समान) के बजाय msvcrt.dll से लिंक करते हैं, जो एक अच्छी योजना है। क्योंकि यह आपके विज़ुअल स्टूडियो के रनटाइम लाइब्रेरी को आपके अंतिम सॉफ़्टवेयर पैकेज के अंदर पुनर्वितरित करने के लिए मुक्त करेगा।

वह समाधान मेरी मदद करता है (विज़ुअल स्टूडियो 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

विजुअल स्टूडियो 6 और इसके कंपाइलर के लिए इस स्निपेट की आवश्यकता नहीं है। इसलिए # शिफा।


0

इस पहले से ही समृद्ध धागे में और अधिक भ्रम लाने के लिए, मैं fprintf पर उसी अनसुलझे बाहरी में टकरा गया

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

यहां तक ​​कि अगर मेरे मामले में यह एक अलग संदर्भ में था: विज़ुअल स्टूडियो 2005 (विज़ुअल स्टूडियो 8.0) के तहत और त्रुटि मेरे अपने कोड में हो रही थी (बहुत ही मैं इसे संकलित कर रहा था), न कि किसी तीसरे पक्ष ने।

ऐसा हुआ कि यह त्रुटि मेरे संकलक झंडे में / एमडी विकल्प द्वारा ट्रिगर की गई थी। / MT पर स्विच करने से समस्या दूर हो गई। यह अजीब है क्योंकि आमतौर पर, स्टेटिकली (एमटी) को जोड़ने से डायनेमिकली (एमडी) की तुलना में अधिक समस्या उठती है ... लेकिन सिर्फ इस मामले में कि यह अन्य कार्य करता है, मैंने इसे वहां रखा।


0

मेरे मामले में, यह त्रुटि मेरे परीक्षण से MSVC- संस्करण आश्रित रनटाइम लाइब्रेरी DLL (msvcr10.dll या तो) पर निर्भरता को दूर करने और / या मेरे निष्पादनयोग्य से अतिरिक्त वसा को हटाने के लिए स्थैतिक रनटाइम लाइब्रेरी को हटाने के लिए आती है।

इसलिए मैं / NODEFAULTLIB लिंकर स्विच का उपयोग करता हूं, मेरे स्व-निर्मित "msvcrt-light.lib" (इसके लिए Google की आवश्यकता होने पर), और mainCRTStartup()/ WinMainCRTStartup()प्रविष्टियां।

यह विजुअल स्टूडियो 2015 के बाद से IMHO है, इसलिए मैं पुराने कंपाइलरों से चिपक गया।

हालाँकि, प्रतीक _NO_CRT_STDIO_INLINE को परिभाषित करने से सभी परेशानी दूर हो जाती है, और एक सरल "हैलो वर्ल्ड" एप्लिकेशन फिर से 3 KB छोटा हो जाता है और असामान्य DLL पर निर्भर नहीं होता है। विजुअल स्टूडियो 2017 में परीक्षण किया गया।


-2

इस कोड को अपनी किसी भी सोर्स फाइल में पेस्ट करें और री-बिल्ड करें। मेरे लिए काम किया!

# डंके की चोट पर

फ़ाइल _iob [3];

फ़ाइल * __cdecl __iob_func (शून्य) {

_iob [0] = * स्टडिन;

_iob [0] = * stdout;

_iob [0] = * stderr;

वापसी _iob;

}


आपको `` `के साथ
फ़ॉर्मेटिंग

हालांकि यह कोड प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है, इससे वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद मिलेगी, और शायद अधिक वोट भी मिलेंगे। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है। कृपया स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें और संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं।
ब्रायन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.