অমীমাংসিত বাহ্যিক প্রতীক __ মিম্প__ফ্রিন্টফ এবং __মম্প _____ob_func, এসডিএল 2


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

আমি ইতিমধ্যে বলতে পারি যে সমস্যাটি ভুল সংযোগ থেকে নয়। আমি সবকিছু সঠিকভাবে সংযুক্ত করেছি, তবে কিছু কারণে এটি সংকলন করবে না।

আমি এসডিএল 2 ব্যবহার করার চেষ্টা করছি।

আমি ভিজুয়াল স্টুডিও 2015 সংকলক হিসাবে ব্যবহার করছি।

আমি লিঙ্কার -> ইনপুট -> অতিরিক্ত নির্ভরতাগুলিতে SDL2.lib এবং SDL2main.lib এর সাথে লিঙ্ক করেছি এবং আমি ভিসি ++ ডিরেক্টরি সঠিক কিনা তা নিশ্চিত করেছি।


1
আপনার লিঙ্কার সেটিংস প্রদর্শন করে আপনি কি প্রমাণ করতে পারেন দয়া করে।
01

@।, আমি ইনপুট লিংকার সেটিংসে 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}

স্টিডিও ফাংশন সম্পর্কিত অন্যান্য লিঙ্ক ত্রুটিগুলি সম্পর্কে (আমার ক্ষেত্রে এটি ছিল sprintf()), আপনি আপনার লিঙ্কার বিকল্পগুলিতে লিগ্যাসি_স্টেডিও_ডিফিনেশনস.লিব যোগ করতে পারেন ।


1
এটি ট্র্যাক করার জন্য ধন্যবাদ। আইআইআরসি {* স্ট্ডিন, * স্টাডআউট, * স্টেডার problem এর সমস্যা হতে পারে যে বিভিন্ন সংকলন ইউনিটের স্ট্যান্ডিনের নিজস্ব নিজস্ব অনুলিপি থাকতে পারে, এই কারণেই এই ফাংশনগুলি সরাসরি ডাকা হত।
স্টিভেন আর লুমিস 21

3
এটি আমার জন্যও সমাধান extern "C"হয়েছে, ঘোষণা / সংজ্ঞা ব্যবহারের জন্য কেবলমাত্র একটি অনুস্মারক ।
ভারগাস

4
প্রতিস্থাপনের ফাংশনটি দেখতে কেমন হওয়া উচিত কেউ লিখতে পারেন? আমি বিভিন্ন বৈকল্পিক চেষ্টা করেছি এবং আমি সংকলন ত্রুটি পেতে থাকি। ধন্যবাদ।
মিলান বাবুভকভ

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

1
উপরের iob_func সংজ্ঞাটি কাজ করে না, সঠিক সংজ্ঞাটির জন্য মার্কএইচের উত্তর দেখুন। (আপনি কেবল অ্যারের হিসাবে কোনও ফাংশন সংজ্ঞায়িত করতে পারবেন না এবং কলগুলি কাজ করার আশা করতে পারবেন না))
হ্যান্স অলসন

59

আইএমও মিলান বাবুস্কোভের প্রতি, প্রতিস্থাপনের কাজটি দেখতে হ'ল :-)

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

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

5
এমএসভিসির জন্য এবং এমএসভিসি সংস্করণ <2015
পলম

1
হিসাবে MarkH অন্য উত্তরে নোট হিসাবে সঠিক দেখায়, কিন্তু কার্যকর হবে না।
হান্স ওলসন

4
@paulm আমার মনে হয় আপনি অর্থ #if defined(_MSC_VER) && (_MSC_VER >= 1900)
জেসি

@ জেসি চিসলম সম্ভবত এটি নির্ভর করে যদি এটি এমএসভিসি-র প্রতিটি জ্ঞাত ভবিষ্যতের সংস্করণেও প্রযোজ্য বা না;)
পলম

42

মাইক্রোসফ্ট এর এ সম্পর্কে একটি বিশেষ দ্রষ্টব্য রয়েছে ( https://msdn.microsoft.com/en-us/library/bb531344.aspx#BK_CRT ):

ফাংশনের প্রিন্টফ এবং স্ক্যানফ পরিবারটি এখন ইনলাইনে সংজ্ঞায়িত করা হয়েছে।

প্রিন্টফ এবং স্ক্যানফ ফাংশনগুলির সমস্ত সংজ্ঞাগুলি ইনডলিকে stdio.h , conio.h , এবং অন্যান্য CRT শিরোনামে সরানো হয়েছে । এটি একটি ব্রেকিং পরিবর্তন যা উপযুক্ত সিআরটি শিরোলেখ ছাড়াই স্থানীয়ভাবে এই ফাংশনগুলি ঘোষণা করে এমন কোনও প্রোগ্রামের জন্য একটি লিঙ্কার ত্রুটির (LNK2019, অমীমাংসিত বহিরাগত প্রতীক) বাড়ে। যদি সম্ভব হয় তবে আপনার সিআরটি শিরোলেখগুলি অন্তর্ভুক্ত করার জন্য কোডটি আপডেট করা উচিত (এটি # অন্তর্ভুক্ত করুন) এবং ইনলাইন ফাংশনগুলি, তবে আপনি যদি এই শিরোলেখ ফাইলগুলিকে অন্তর্ভুক্ত করতে আপনার কোডটি পরিবর্তন করতে না চান তবে বিকল্প সমাধানটি অতিরিক্ত যুক্ত করা হয় আপনার লিঙ্কারের ইনপুটটিতে লাইব্রেরি, লিগ্যাসি_স্টডিও_ডিফাইনিশন.লিব

আইডিইতে আপনার লিঙ্কার ইনপুটটিতে এই লাইব্রেরিটি যুক্ত করতে, প্রকল্প নোডের জন্য প্রসঙ্গ মেনু খুলুন, বৈশিষ্ট্যগুলি নির্বাচন করুন, তারপরে প্রকল্পের বৈশিষ্ট্যগুলি ডায়ালগ বাক্সে লিংক চয়ন করুন, এবং লিগেরি ইনপুট সম্পাদনা করুন লিগ্যাসি_স্টডিয়ো_ডিফিনিশনস.লিবকে আধা-কোলনে যোগ করুন - প্রস্তুত তালিকা।

যদি আপনার প্রকল্পটি 2015 এর আগে ভিজ্যুয়াল সি ++ প্রকাশের সাথে সংকলিত স্থিত লাইব্রেরির সাথে লিঙ্ক করেছে, লিঙ্কারটি অমীমাংসিত বহিরাগত প্রতীক হিসাবে রিপোর্ট করতে পারে। এই ত্রুটিগুলি _iob , _iob_func , বা নির্দিষ্ট স্টিডিও ফাংশনের জন্য সম্পর্কিত আমদানি __imp_ * আকারে অভ্যন্তরীণ স্টিডিও সংজ্ঞা উল্লেখ করতে পারে। মাইক্রোসফ্ট সুপারিশ করে যে আপনি যখন কোনও প্রকল্প আপগ্রেড করবেন তখন আপনি সমস্ত স্ট্যাটিক লাইব্রেরি ভিজ্যুয়াল সি ++ সংকলক এবং লাইব্রেরিগুলির সর্বশেষ সংস্করণ সহ পুনরায় সংকলন করুন। লাইব্রেরি যদি কোনও তৃতীয় পক্ষের লাইব্রেরি হয় তবে যার উত্সটি উপলভ্য নয়, আপনার উচিত হয় তৃতীয় পক্ষের কাছ থেকে একটি আপডেট বাইনারি অনুরোধ করা উচিত বা সেই লাইব্রেরির একটি পৃথক ডিএলএল ব্যবহার করা উচিত যা আপনি ভিজ্যুয়াল সি ++ সংকলকের পুরানো সংস্করণ দিয়ে সংকলন করেন এবং লাইব্রেরি।


7
বা #pragma comment(lib, "legacy_stdio_definitions.lib")- তবে এটি ঠিক করে না __imp___iob_func- এর জন্য কি কোনও উত্তরাধিকারের লিওব রয়েছে?
bytecode77

29

উপরে উত্তর হিসাবে, সঠিক উত্তরটি হ'ল ভিএস ২০১৫ এর সাথে সমস্ত কিছু সংকলন করা, তবে আগ্রহের জন্য নিম্নলিখিতটি আমার সমস্যা বিশ্লেষণ।

এই প্রতীকটি মাইক্রোসফ্ট দ্বারা সরবরাহিত কোনও স্থির গ্রন্থাগারে VS2015 এর অংশ হিসাবে সংজ্ঞায়িত বলে মনে হয় না, যা অন্য সমস্ত কারণেই বরং অদ্ভুত। কেন তা আবিষ্কার করার জন্য আমাদের সেই ফাংশনটির ঘোষণাপত্র এবং আরও গুরুত্বপূর্ণভাবে এটি কীভাবে ব্যবহৃত হচ্ছে তা লক্ষ্য করা উচিত।

এখানে ভিজ্যুয়াল স্টুডিও ২০০ 2008 শিরোনামের একটি স্নিপেট রয়েছে:

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

সুতরাং আমরা দেখতে পাচ্ছি যে ফাংশনটির কাজটি হ'ল ফাইলের একটি অ্যারের প্রারম্ভ ফিরিয়ে আনা (হ্যান্ডলগুলি নয়, "ফাইল *" হ্যান্ডেলটি, ফাইলে গুরুত্বপূর্ণ স্টেটের গুডিকে স্টোর করে অন্তর্নিহিত অস্বচ্ছ ডেটা স্ট্রাকচার)। এই ফাংশনটির ব্যবহারকারীরা হলেন তিনটি ম্যাক্রো স্টিডিন, স্টডআউট এবং স্টার্ডার যা বিভিন্ন 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 সরবরাহ করতে পারি না? মাইক্রোসফ্ট __iob_func এর মাধ্যমে তাদের মূল প্রয়োগের ক্ষেত্রে লঙ্ঘন করতে পারে না এমন দুটি মূল বিধি রয়েছে:

  1. সেখানে তিনটি ফাইল স্ট্রাকচারের অ্যারে থাকতে হবে যা পূর্বের মতো একই পদ্ধতিতে সূচকযুক্ত হতে পারে।
  2. 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, আইওব [1] অফসেট 4 এবং _iob [2] অফসেটে 8 রয়েছে The কলিং কোডটি তার পরিবর্তে আমার সিস্টেমে 32 বাইটে সারিবদ্ধভাবে ফাইলটি প্রত্যাশা করবে এবং তাই এটি ফিরে আসা অ্যারের ঠিকানা গ্রহণ করবে এবং মৌলিক শূন্যটি পেতে 0 বাইট যুক্ত করবে (এটি একটি ঠিক আছে) তবে _ আইওব [1] এর জন্য এটি ব্যয় করতে হবে যে 32 বাইট যুক্ত করতে হবে এবং _ আইওব [2] এর জন্য এটি হ্রাস পাবে এটিতে 64৪-বাইট যুক্ত করা দরকার (কারণ এটি ভিএস ২০০৮ শিরোলেখগুলিতে কেমন দেখায়)। এবং সত্যই VS2008 এর জন্য বিযুক্ত কোডটি এটি দেখায়।

উপরের সমাধান সহ একটি গৌণ সমস্যা হ'ল এটি ফাইলের কাঠামোর (* স্টিডিন) বিষয়বস্তু অনুলিপি করে, ফাইল * হ্যান্ডেলটি নয়। সুতরাং যে কোনও ভিএস ২০০৮ কোড ভিএস ২০১৫ এ অন্য অন্তর্নিহিত কাঠামোটির দিকে চেয়ে থাকবে। কাঠামোটিতে কেবলমাত্র পয়েন্টার থাকলে এটি কাজ করতে পারে তবে এটি একটি বড় ঝুঁকি। যে কোনও ক্ষেত্রে প্রথম ইস্যুটি এই অপ্রাসঙ্গিক উপস্থাপন করে।

আমি যে হ্যাকটি স্বপ্ন দেখতে পেরেছি তা হ'ল এটির মধ্যে __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 আপডেট ব্যবহার করার জন্য আমার ভিজ্যুয়াল স্টুডিও 2013 থেকে অনেকগুলি প্রকল্প (সি ++ এবং সি # প্রকল্প) আপগ্রেড করতে হবে 3. যেমন উপরে. আমি লিঙ্কারে লিগ্যাসি_স্টডিও_ডিফিনিশন.লিব যোগ করে ইমপ _ফপ্রিন্টফ স্থির করেছি । আমি কীভাবে _ আইপিএপিওওব_ফঙ্ক ঠিক করতে পারি ?
মোহাম্মদ বউজিদি

আমার পূর্ববর্তী প্রশ্নের উত্তর দেওয়ার আগে, এম + এস প্রকল্পগুলি সংকলন করতে এমএসবিল্ড 14 এবং ইন্টেলকম্পিলার 2016 এবং ভিসি 100 ব্যবহার করার সময় এই ত্রুটিগুলি কি স্বাভাবিক হয়?
মোহাম্মদ বউজিদি

1
একটি x 64 সংকলনের জন্য আমি কী করতে পারি?
এথোস 4'99

28

আমার ভিএস ২০১৫ এ একই সমস্যা ছিল। আমি ভিএস ২০১৫-তে এসডিএল 2 উত্সগুলি সংকলন করে সমাধান করেছি।

  1. Http://libsdl.org/download-2.0.php এ যান এবং এসডিএল 2 উত্স কোড ডাউনলোড করুন।
  2. VS2015 এ SDL_VS2013.sln খুলুন । আপনাকে প্রকল্পগুলি রূপান্তর করতে বলা হবে। এটা কর.
  3. এসডিএল 2 প্রকল্পটি সংকলন করুন।
  4. SDL2main প্রকল্পটি সঙ্কলন করুন।
  5. VS2015 এ আপনার এসডিএল 2 প্রকল্পে নতুন উত্পন্ন আউটপুট ফাইলগুলি SDL2main.lib, SDL2.lib এবং SDL2.dll ব্যবহার করুন।

4
বিটিডাব্লু, এসডিএল ২.০.৩ নির্মাণের জন্য জুন ২০১০ ডাইরেক্টএক্স এসডিকে ইনস্টল করা প্রয়োজন।
জো

1
আমার জন্য কাজ, ধন্যবাদ !! তবে আমার কেবল SDL2mainSDL2main.lib
কমপিউলে

10

আমি জানি না তবে কেন:

#ifdef main
#undef main
#endif

অন্তর্ভুক্ত করার পরে তবে আপনার প্রধানটিকে আমার অভিজ্ঞতা থেকে এটি ঠিক করা উচিত।


1
.... ঠিক আছে .... তাই চেষ্টা করার আগে আমি শ্রুতিমধুর হয়ে নিজেকে বলেছিলাম যে একরকম সন্দেহ হচ্ছে এটি কাজ করতে চলেছে তবুও এটি সম্পূর্ণভাবে ঘটেছে ..... আপনি ব্যাখ্যা করতে পারেন কেন এই কাজ করে ...?
ট্রেভর হার্ট

1
@ ট্রেভর হার্ট আমি বিশ্বাস করি যে এটি একটি "ত্রুটিযুক্ত" এসডিএল প্রধানকে "অপরিজ্ঞাত " বাফারগুলির অন্তর্ভুক্ত রেফারেন্সগুলিকে সংজ্ঞায়িত করে এবং যদি আপনার বাফারগুলি আপনার ব্যবহার করে, তবে এটি সমস্ত ভাল এবং ভাল কাজ করে।
এক্সগুড

2
এটি ভয়ঙ্কর খারাপ অনুশীলন হ্যাক তবে এটি 3 টি লাইন এবং এটি কাজ করে এবং এটি আমাকে রবিবিথোল থেকে এসডিএল তৈরির হাত থেকে রক্ষা পেয়েছিল ... সুন্দরভাবে সম্পন্ন হয়েছে।
চিজমিস্টার

1
@ চেজমিস্টার খারাপ অভ্যাস এবং হ্যাকগুলি প্রায়শই প্রতিটি কিছুর জন্য প্রয়োজন। বিশেষত যে জিনিসগুলির তাদের প্রয়োজন হবে না।
এক্সগুড

8

এই সমস্যার আরও সাম্প্রতিক সমাধান: আরও সাম্প্রতিক এসডিএল লিব ব্যবহার করুন

" 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*সি-অ্যারে ফিরিয়ে দেওয়া উইন্ডোজের অভ্যন্তরীণ আইওবি স্ট্রাইকগুলির সাথে মেলে না। @Volker অধিকার যে এটা হবে না একাধিক কাজ stdin, stdoutবাstderr

কোনও লাইব্রেরি যদি সেই স্ট্রিমগুলির মধ্যে একটি ব্যবহার করে তবে তা ক্রাশ হবে । যতক্ষণ না আপনার প্রোগ্রামটি lib এগুলি ব্যবহার না করে, আপনি কখনই জানতে পারবেন না । উদাহরণস্বরূপ, png_default_errorথেকে লিখেছেন stderrযখন সিআরসি পিএনজি মেটাডাটা মধ্যে মিলছে না। (সাধারণত ক্র্যাশ-যোগ্য সমস্যা নয়)

উপসংহার: VS2012 (প্ল্যাটফর্ম টুলসেট v110 / v110_xp) এবং VS2015 + লাইব্রেরিগুলি মিশ্রণ করা সম্ভব নয়, যদি তারা স্টিডিন, স্টাডআউট এবং / অথবা স্ট্যাডার ব্যবহার করে।

সমাধান: আপনার লাইব্রেরিগুলিকে পুনরায় সংকলন __iob_funcকরুন যা আপনার ভিএস এর বর্তমান সংস্করণ এবং একটি ম্যাচিং প্ল্যাটফর্ম টুলসেটের সাথে অমীমাংসিত চিহ্ন রয়েছে।



2

আমি নিম্নলিখিত ফাংশন দিয়ে এই সমস্যাটি সমাধান করি। আমি ভিজ্যুয়াল স্টুডিও 2019 ব্যবহার করি।

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

কারণ স্টিডিন ম্যাক্রো সংজ্ঞায়িত ফাংশন কল, "* স্টিডিন" এক্সপ্রেশনটি গ্লোবাল অ্যারে ইনিশিয়ালাইজার ব্যবহার করতে পারে না। তবে স্থানীয় অ্যারে প্রারম্ভিক সম্ভব is দুঃখিত, আমি ইংরেজিতে দরিদ্র


1

যে কেউ এখনও উত্তরটির সন্ধান করছেন যেখানে উপরের কৌশলগুলি কার্যকর হয়নি। স্ট্যাটিক লিঙ্কিং এই সমস্যাটি সমাধান করার উপায়। নীচে হিসাবে আপনার রানটাইম লাইব্রেরি সেটিংস পরিবর্তন করুন

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


এই সমাধানের জন্য এখানে একটি আলোচনা এখানে দেওয়া হয়েছে: social.msdn.microsoft.com/ Forums
সিসির

0

আমি সমস্যার সমাধান করতে পেরেছি।

ত্রুটির উত্স ছিল কোডের এই লাইন, যা এসডিএলমেইন উত্স কোডে পাওয়া যাবে।

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

সুতরাং আমি যা করেছি তা হ'ল সেই লাইনের এসডিএলমেইনে উত্স কোডটি সম্পাদনা করা:

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

এবং তারপরে আমি SDLmain তৈরি করেছি এবং আমার নির্মিত SDL2 লাইব্রেরি ডিরেক্টরিতে পুরানো SDLmain.lib অনুলিপি করেছি এবং নতুনভাবে নির্মিত এবং সম্পাদনা করেছি।

তারপরে যখন আমি এসডিএল 2 দিয়ে আমার প্রোগ্রামটি চালিত করি তখন কোনও ত্রুটি বার্তা উপস্থিত হয় নি এবং কোডটিতে সহজেই দৌড়ায়।

এটি পরে আমাকে কামড় দেবে কিনা আমি জানি না, তবে তাই সব কিছু দুর্দান্ত চলছে।


আপনার পরিবর্তনটি নিজের এবং নিজেই একটি ভুল এবং আপনার প্রশ্নের বর্ণিত সমস্যাটি সমাধান করতে পারত না। এটি কেবল একটি কাকতালীয় বিষয় যে আপনি আর লিঙ্কারের ত্রুটিগুলি পাচ্ছেন না, এটি সম্ভবত আপনি লাইব্রেরিটি কীভাবে পুনর্নির্মাণ করেছেন তার একমাত্র ফলাফল।
রস রিজ

@ রোসরিজ, ওহ হ্যাঁ যে সম্ভবত এটিই হতে পারে। আহ ভালো.
রকফ্রেঞ্জি

0

আপনি যখন msvcr10.dll (বা অনুরূপ) এর পরিবর্তে msvcrt.dll এর সাথে লিঙ্ক করবেন তখন এটি ঘটতে পারে, যা একটি ভাল পরিকল্পনা। কারণ এটি আপনাকে চূড়ান্ত সফ্টওয়্যার প্যাকেজের ভিতরে আপনার ভিজ্যুয়াল স্টুডিওর রানটাইম লাইব্রেরি পুনরায় বিতরণ করতে মুক্ত করবে।

এই কর্মপরিকল্পনা আমাকে সহায়তা করে (ভিজ্যুয়াল স্টুডিও ২০০৮ এ):

#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 এবং এর সংকলকটির প্রয়োজন নেই। অতএব #ifdef।


0

ইতিমধ্যে সমৃদ্ধ এই থ্রেডে আরও বিভ্রান্তি আনতে, আমি এফপ্রিন্টএফ-তে একই অমীমাংসিত বহিরাগতকে টুকরো টুকরো করে ফেলি

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

এমনকি যদি আমার ক্ষেত্রে এটি একটি ভিন্ন প্রসঙ্গে ছিল: ভিজ্যুয়াল স্টুডিও 2005 এর অধীনে (ভিজ্যুয়াল স্টুডিও 8.0) এবং ত্রুটিটি আমার নিজস্ব কোডে ঘটছিল (একইভাবে আমি সংকলন করছি), তৃতীয় পক্ষ নয় not

এটি ঘটেছিল যে এই ত্রুটিটি আমার সংকলক পতাকাগুলিতে / MD বিকল্প দ্বারা ট্রিগার করা হয়েছিল। / এমটি-তে স্যুইচ করা বিষয়টি মুছে ফেলে। এটি অদ্ভুত কারণ সাধারণত স্ট্যাটিকালি সংযুক্তি (এমটি) ডায়নামিকভাবে (এমডি) এর চেয়ে বেশি সমস্যা উত্থাপন করে ... তবে কেবল যদি এটি অন্যকে কাজ করে তবে আমি এটি সেখানে রেখেছি।


0

আমার ক্ষেত্রে, আমার এক্সিকিউটেবলগুলি থেকে অতিরিক্ত মেদ অপসারণ করতে এমএসভিসি-সংস্করণ নির্ভর রানটাইম লাইব্রেরি ডিএলএল (এমএসভিসিআর 10.ডিল বা তাই) এবং / অথবা স্ট্যাটিক রানটাইম লাইব্রেরি অপসারণের জন্য এই ত্রুটিটি আমার পরীক্ষার মধ্য দিয়ে এসেছে।

সুতরাং আমি / নোডাফলটিআইবি লিঙ্কার স্যুইচ, আমার স্ব-তৈরি "এমএসভিসিআরটি-লাইট.লিব" (যখন আপনার প্রয়োজন হবে তার জন্য গুগল) এবং mainCRTStartup()/WinMainCRTStartup() এন্ট্রি ব্যবহার করি।

এটি ভিজুয়াল স্টুডিও 2015 সাল থেকে আইএমএইচও, তাই আমি পুরানো সংকলকগুলিতে আটকেছি।

তবে, _NO_CRT_STDIO_INLINE প্রতীকটি সংজ্ঞায়িত করা সমস্ত ঝামেলা সরিয়ে দেয় এবং একটি সাধারণ "হ্যালো ওয়ার্ল্ড" অ্যাপ্লিকেশনটি আবার 3 কেবি ছোট এবং অস্বাভাবিক ডিএলএলগুলির উপর নির্ভর করে না। ভিজ্যুয়াল স্টুডিও 2017 এ পরীক্ষিত।


-2

আপনার যে কোনও উত্স ফাইলগুলিতে এই কোডটি আটকান এবং পুনর্নির্মাণ করুন। আমার জন্য কাজ!

# অন্তর্ভুক্ত করুন stdio.h

ফাইল _iob [3];

ফাইল * __cdecl __iob_func (শূন্য) {

_আইব [0] = * স্টিডিন;

_আইব [0] = * স্টডআউট;

_আইব [0] = * স্টাডার;

প্রত্যাবর্তন _iob;

}


আপনার `` with এর সাথে ফর্ম্যাট এবং কিছু ব্যাখ্যা যুক্ত করা উচিত
আন্তোনিন গ্যাভারিল

এই কোডটি কীভাবে এবং কেন এই সমস্যার সমাধান করে তার ব্যাখ্যা সহ প্রশ্নটি সমাধান করতে পারে যদিও আপনার পোস্টের মান উন্নত করতে সত্যিই সহায়তা করবে এবং সম্ভবত আরও বেশি ভোটের ফলাফল হবে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, কেবল এখন যে ব্যক্তি জিজ্ঞাসা করছেন তা নয়। দয়া করে সম্পাদনা ব্যাখ্যা যোগ করতে পারেন এবং সীমাবদ্ধতা এবং অনুমানের কি প্রয়োগ একটি ইঙ্গিত দিতে আপনার উত্তর।
ব্রায়ান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.