none
(MSVCRT) _iob disappeared?

    Question

  • What can I do to replace the functionality of _iob? Seems to be missing in MSVCR7/8 (using VS2005).
    Sunday, June 11, 2006 4:32 AM

Answers

  • To resolve the issue, I made stubs in my main code:

    ...
    void _acmdln( ) { }
    void __pioinfo( ) { }
    void __badioinfo( ) { }

    ...

    The compiler still went through the .def and properly linked my exports to their real outside counterparts. Go figure!
    Sunday, June 11, 2006 7:11 PM
  • Hi,

    In VC++ 2005,  CRT has correctly stopped aliasing __iob to __imp___iob. Code that uses __iob never worked correctly when compiled in VS2003 anyway.

     __gapman__ wrote:

    error LNK2001: unresolved external symbol __iob
    from within the static third party library

    This is a sign of an attempt to link together code from VS2005 with static library build with VS2003. This is not going to work unfortunately. You have to rebuild this static library with VS2005.

     

    Thanks,
    Nikola

     

     

    Thursday, July 06, 2006 1:42 AM
  •  bxs122 wrote:
    But what if rebuilding the static lib in VS2005 is not an option?

    It should be possible to define it yourself. Look in CRT sources on how it is defined in CRT and work out how you may define it in your code so the linker finds it during the build.

    Nikola

    Thursday, July 06, 2006 4:04 PM

All replies

  • It is definitely still there - exactly what kind of errors/behavior are you seeing?
    Sunday, June 11, 2006 5:23 AM
  • Error 1 error LNK2001: unresolved external symbol _iob main.def

    In my def, I'm redirecting this export as such:

    _iob=MSVCR80._iob

    I also tried:

    _iob=MSVCRT._iob

    Sunday, June 11, 2006 5:24 AM
  • Can you tell me what you want with the _iob FILE table? Usually there is no need to access this table, also its not public and for internal use only.

    Also there might be a trick to access the _iob FILE array. stdin is always at &_iob[0]...

    Sunday, June 11, 2006 10:51 AM
  • The library I'm building is being used as a "proxy" if you will for API monitoring/research purposes. I have to handle all exported functions from the original. What gets me is the fact these old internal symbols (_iob, _acmdln, etc) are actively used in Windows Vista applications...
    Sunday, June 11, 2006 4:54 PM
  • To resolve the issue, I made stubs in my main code:

    ...
    void _acmdln( ) { }
    void __pioinfo( ) { }
    void __badioinfo( ) { }

    ...

    The compiler still went through the .def and properly linked my exports to their real outside counterparts. Go figure!
    Sunday, June 11, 2006 7:11 PM
  •  Rafael Rivera wrote:
    What gets me is the fact these old internal symbols (_iob, _acmdln, etc) are actively used in Windows Vista applications...

    I still don't understand why you need to access this fields directly. They are still internal (undocumented)! When a program links to it it is normal, at least because even this internal (undocumented) gets exported and are used by macros.

    Monday, June 12, 2006 6:02 AM
  • Let me try to explain in a different way:

    Program A that makes use of _iob is importing from DLL A.
    I'm replacing DLL A with DLL B that proxies requests to DLL A via MSR Detours.
    DLL B has to support everything DLL A did.

    Or in another more graphical way:

    old: my.exe <-- imports -- _iob (msvcrt.dll)
    new: my.exe <-- imports -- _iob (proxy.dll) <-- imports -- _iob (msvcrt.dll)

    Hope that clears things up. By the way, is the above bug acknowledged/reproducable by you guys?


    Monday, June 12, 2006 7:30 PM
  • I've seen the __iob problem as well... I'm trying to make a mixed managed/native C++ wrapper for a static third party library.  Upon linking, I get errors saying various symobls are already defined.

    E.g. libcmt.lib(mlock.obj) : error LNK2005: __unlock already defined in MSVCRTD.lib(MSVCR80D.dll)

    I get over 20 errors... so then I tried changing the linker settings to "Ignore Specific Library" for libcmt.lib.  Then when I build I get rid of all the "already defined" errors and instead end up with just:

    error LNK2001: unresolved external symbol __iob
    from within the static third party library

    So it would seem that __iob is not defined in MSVCRTD.lib... but is defined in libcmt.lib.

    It also means I am stuck... how can I link my wrapper?




    Tuesday, June 13, 2006 3:37 PM
  • Here's the interesting thing -- It's there!

    dumpbin msvcrtd.lib /all | grep iob

      <snip>
      Symbol name  : __iob
      Name         : _iob

      Symbol name  : ___p__iob
      Name         : __p__iob
      Symbol name  : ___iob_func
      Name         : __iob_func
      <snip>

     

    Tuesday, June 13, 2006 10:17 PM
  • It is not necessary for the developer to access _iob directly for this problem to occur.  We're running into the same problem when linking with libs which were compiled under VC 6. 

    It could be that any lib calling printf() family functions wind up compiling a reference to _iob into the  executable/library.  
    Thursday, June 22, 2006 4:42 PM
  • The exported name for _iob is __iob (two underscores); that's the name you need in the .def file.
    Saturday, July 01, 2006 6:29 PM
  • Hello,

    I'm facing exactly the same problem.  I need to compile with a library that was compiled using VC 6.0. Of course I have no way to recompile this library as it's part of a product from another company.

    Did someone have a way to avoid this problem ? I tried to make some stubs, I check in the header file (stdio.h, wchar.h) and so on...

    Many thanks in advance

    Laurent Flahou

    Tuesday, July 04, 2006 8:25 AM
  • MSVC6 references _iob in the stdio.h and wchar.h include files.  Using stdin, stdout, stderr, getwchar() or putwchar() creates a reference to _iob in the .lib file.  I created a test program that uses _iob:

    #include "stdafx.h"
    #include <stdio.h>

    // This is how stdin is declared in MSVC6' stdio.h:
    extern "C" extern FILE _iob[];
    #undef stdin
    #define stdin (&_iob[0])

    int _tmain(int argc, _TCHAR* argv[])
    {
      // Force a reference to stdin:
      fread(stdin, 0, 0, 0);
      return 0;
    }

    When I compile this, I get "error LNK2001: unresolved external symbol __iob".  Project + Properties, C/C++, Code generation, Runtime library = Multi-thread Debug (/MTd).  Now the program compiles and links without problems.

    The problem is clearly caused by the DLL version of the CRT not exporting the __iob symbol.  The solution is to statically link the CRT.

    Tuesday, July 04, 2006 1:51 PM
  • Ayman hates an unanswered thread and brings in the troops to get it resolved.  I'm going to mark this thread unanswered, my apologies to everybody that got the answer assigned originally...

    Ayman: you're a fantastic program manager and a shining example of a great MSFT employee. And thanks for the answers...

    Tuesday, July 04, 2006 9:40 PM
  • Hi,

    In VC++ 2005,  CRT has correctly stopped aliasing __iob to __imp___iob. Code that uses __iob never worked correctly when compiled in VS2003 anyway.

     __gapman__ wrote:

    error LNK2001: unresolved external symbol __iob
    from within the static third party library

    This is a sign of an attempt to link together code from VS2005 with static library build with VS2003. This is not going to work unfortunately. You have to rebuild this static library with VS2005.

     

    Thanks,
    Nikola

     

     

    Thursday, July 06, 2006 1:42 AM
  • Has there been any updates to this -- I am faced with the same error and unable to move forward until I get a work-around for this.

    As mentioned nobody needs access direct to the _iob tables, the error 

    error LNK2001: unresolved external symbol __iob

     comes up when linking to a static lib from some third parties.

    Thanx

    Thursday, July 06, 2006 2:41 AM
  • See Nikola's reply on this thread.

    Thanks,
    Ayman Shoukry
    VC++ Team
    Thursday, July 06, 2006 6:15 AM
  • But what if rebuilding the static lib in VS2005 is not an option?
    Thursday, July 06, 2006 11:11 AM
  • Thanks Nikola.  Will code that links the CRT statically function correctly if it references _iob?

    Thursday, July 06, 2006 2:09 PM
  •  bxs122 wrote:
    But what if rebuilding the static lib in VS2005 is not an option?

    It should be possible to define it yourself. Look in CRT sources on how it is defined in CRT and work out how you may define it in your code so the linker finds it during the build.

    Nikola

    Thursday, July 06, 2006 4:04 PM
  •  nobugz wrote:
    Will code that links the CRT statically function correctly if it references _iob?

    Yes, it should be fine. But you have to avoid linking to static CRT whenever possible because of issues around servicing CRT and issues around per-module data stored in CRT. And you should be avoiding using static libraries in your application for which you don't have source code, especially when they are staticly linked to CRT. Linking to dynamic CRT is almost always the right setup. As for libraries, they should be packaged either as DLLs with exports that use only simple Win32 or built-in types or as COM objects or as .Net assemblies.

    Nikola

    Thursday, July 06, 2006 4:20 PM
  •  Nikola Dudar - MSFT wrote:

     bxs122 wrote:
    But what if rebuilding the static lib in VS2005 is not an option?

    It should be possible to define it yourself. Look in CRT sources on how it is defined in CRT and work out how you may define it in your code so the linker finds it during the build.

    Nikola

    I am not certain you can define it yourself - well I guess you can define it but what if the third part lib runtime references it? What is the best way to define it from the VS2005 side?

    Thursday, July 06, 2006 4:25 PM
  • Hello,

    I had a similar problem in VS2005, and looking at stdio.h showed me this:

    stdio.h(160): #define stdout (&__iob_func()[1])

    So I replaced _iob[1] with __iob_func()[1] in my files, and it worked. Hope it solves your problems as well.

    regards,

    Bart
    Monday, July 10, 2006 12:23 PM
  • I found the declaration in stdio.h but when reading the remainder of your email you mention you replaced it in your files? In my case a third party static lib is referencing it which is causing the unresolved external. I am not sure what I would replace in my files - I think if I declare anything in my files it will result in a compile error since it is already declared in stdio.h.

    What exactly did you put in your code?

    Thanx

    Monday, July 10, 2006 12:29 PM
  • Ah, now I see the problem, with this legacy code. Well, I'm not that an expert on this depth-level of C(++), but what if you would try to put somewhere in your code the original declaration of _iob. I don't have the previous stdio.h anymore, but it must look sth like this:

    FILE *_iob;

    And then assign the new stdio.h pointers to _iob:

    _iob[0] = __iob_func()[0]
    _iob[1] = __iob_func()[1]
    _iob[2] = __iob_func()[2]

    I'm typing this without having tested it, so if I would be already more or less correct, there might be some * or & missing here or there. But I still hope it helps.

    regards,

    bart
    Tuesday, July 11, 2006 3:16 PM
  • While you can initialize an array outside of the body of a function, I don't think you can make assignments to it, so the code snippet should look more like this:

    FILE _iob[3] = {__iob_func()[0], __iob_func()[1], __iob_func()[2]};
    Tuesday, July 18, 2006 8:51 AM
  • I have DLL project, which includes 3-rd party static libs which i can't update. I tried including

    FILE _iob[3] = {__iob_func()[0], __iob_func()[1], __iob_func()[2]};

    in my code, but 3-rd party lib still doesn't see it. Was anybody actually able to make it work?

    Sunday, September 03, 2006 7:34 AM
  •  Nikola Dudar - MSFT wrote:

    It should be possible to define it yourself. Look in CRT sources on how it is defined in CRT and work out how you may define it in your code so the linker finds it during the build.

    Nikola

    Nikola - can you elaborate? Please?

    Friday, September 08, 2006 2:21 PM
  • Did you export it?
    Friday, September 15, 2006 12:59 AM
  • Stupid me... i forgot extern "C" - so it wasn't matching C++ mangled name to __iob. So - solution is to include somewhere in the code following line:

    extern "C" { FILE _iob[3] = {__iob_func()[0], __iob_func()[1], __iob_func()[2]}; }

    What a relief...

    Saturday, September 16, 2006 6:10 AM
  • Raymond Chen details one of many problems linking with a lib/dll that wasn't compiled with the same CRT in his blog entry "Allocating and freeing memory across module boundaries".
    Saturday, September 16, 2006 2:40 PM
  •  Bart Masschelein wrote:
    Hello,

    I had a similar problem in VS2005, and looking at stdio.h showed me this:

    stdio.h(160): #define stdout (&__iob_func()[1])

    So I replaced _iob[1] with __iob_func()[1] in my files, and it worked. Hope it solves your problems as well.

    regards,

    Bart


    I'm trying to compile OSSIM, a large C++ imaging program, in VS2005.
    error LNK2001: unresolved external symbol __iob was the error that came up and doing what Bart described removed this(removing the _func in stdio.h), but it also seem to break functions related to stdin/stdout/stderr such as :


    858     fprintf(stderr, "hit RETURN to continue...");
    859     i=getc(stdin);

    with these errors:
    .\..\ossim_core\vpf_util\vpftable.c(858) : error C2198: 'fprintf' : too few arguments for call
    ..\..\ossim_core\vpf_util\vpftable.c(859) : error C2109: subscript requires array or pointer type
    ..\..\ossim_core\vpf_util\vpftable.c(859) : error C2198: 'getc' : too few arguments for call

    Any ideas?
    Thursday, February 01, 2007 8:58 PM
  •  tommy chheng wrote:
     Bart Masschelein wrote:
    Hello,

    I had a similar problem in VS2005, and looking at stdio.h showed me this:

    stdio.h(160): #define stdout (&__iob_func()[1])

    So I replaced _iob[1] with __iob_func()[1] in my files, and it worked. Hope it solves your problems as well.

    regards,

    Bart


    I'm trying to compile OSSIM, a large C++ imaging program, in VS2005.
    error LNK2001: unresolved external symbol __iob was the error that came up and doing what Bart described removed this(removing the _func in stdio.h), but it also seem to break functions related to stdin/stdout/stderr such as :


    858     fprintf(stderr, "hit RETURN to continue...");
    859     i=getc(stdin);

    with these errors:
    .\..\ossim_core\vpf_util\vpftable.c(858) : error C2198: 'fprintf' : too few arguments for call
    ..\..\ossim_core\vpf_util\vpftable.c(859) : error C2109: subscript requires array or pointer type
    ..\..\ossim_core\vpf_util\vpftable.c(859) : error C2198: 'getc' : too few arguments for call

    Any ideas?
    Not surprising using version-specific, undocumented items causes problems...  the only *real* solution is to make sure all the LIBs you link with link to the same CRT as the one you're using in your application.  This means getting VC2005 versions of all the LIBs you're using, if you're using VC2005.  Any other configuration is simply not supported, and never will be.
    Thursday, February 01, 2007 9:11 PM
  • I had this problem (third party library not finding __iob) and solved it by linking to the MFC static library rather than the DLL.

    Project properties dialog

    -> Configuration Properties ->General->Use of MFC->Use MFC in a Static Library

    True static libraries are not good from an update standpoint, but Microsoft should fix the problem by exporting __iob in the DLL.

     

    Saturday, November 20, 2010 12:44 AM
  • Yes, static linking is the way to solve this problem. What I have done is:

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

    Thursday, August 11, 2011 1:38 AM