none
0xc00000005 error

    Question

  • Hi all,

    How do begin to debug this?

    I'm using Visual Studio 2005 SP1, standard edtion on an XP box running SP3.

    Everything was working fine until I reformatted my C drive.  After re-installing everything, things are mostly good but all of my .NET apps have trouble when I try to call unmanaged code.

    A simple 'Hello world' type program works fine.  It then insert a call to a funtion in one of our home grown dll's and I get the 0xc0000005 error.  The IDE tells me:

    Debugger:: An unhandled non-continuable exception was thrown during process load
    The program '[5980] TRHistoryWnd.exe: Native' has exited with code -1073741819 (0xc0000005).

    The code I'm trying to call is as follows:

    /*=====================================================================*  
     
                   bai_msdelay  
                   ---------  
     
      DESC: Delays execution by the specified number of milliseconds  
            This only delays a little while at a time. That way, if you're  
            in the debugger, you can figure out what's happening.  
     
      RETURNS: n.a.  
     
     *=====================================================================*/  
     
    void  bai_msdelay (long milliseconds)  
    {  
       #define DELAY_AMT    100L  
       long                 delay_time;  
     
       while (milliseconds > 0)  
       {  
          if (milliseconds > DELAY_AMT)  
             delay_time  =  DELAY_AMT;  
          else  
             delay_time  =  milliseconds;  
     
          #if defined (__QNX__)  
             (void)  
          #endif  
          delay ((unsigned int) delay_time);  
          milliseconds   -delay_time;  
       }  
    }  
     

    It lives in a DLL named, bctools.dll.  I can give my solution to other developers and it works fine for them.  So, it seems to be a problem with my PC.

    I've tried:
    1. Uninstalling .NET 2.0 SP1 and installing pre sp1 .NET.  Then updated to SP1.
    2. Repair VS install.
    3. Uninstall VS, and re-install from scratch
    4. Dependency Walker shows that I'm missing 'dwmapi.dll' but it seems that this would only be a problem if I was running Vista.  In any case, I provided a dll with the missing DwmExtendFrameIntoClientArea function but it didn't help.
    5. I can give other developers my executable file and that works for them as well.

    I'm stuck here, any ideas?

    Thanks,
    Brian

    Tuesday, June 24, 2008 1:23 PM

Answers

  • __declspec(thread) declarators on variables have several draconian restrictions.  You've violated on of the rules spelled out in this MSDN library article.   There's no clean error detection either, just bam! AV. 
    Hans Passant.
    Tuesday, June 24, 2008 6:24 PM
    Moderator

All replies

  • You won't get anywhere until you start debugging this exception.  Use Debug + Exceptions to force the debugger to stop when the exception is thrown.
    Hans Passant.
    Tuesday, June 24, 2008 3:10 PM
    Moderator
  • I've turned on everything I can see in the IDE and it doesn't let me do anthing.  However, I noticed in another post that it was suggested that ntsd be used (never had heard of it before).  So, I tried it and it yields the following:

    Microsoft (R) Windows User-Mode Debugger  Version 5.1.2600.0
    Copyright (c) Microsoft Corporation. All rights reserved.

    CommandLine: TRHistoryWnd.exe
    Loaded dbghelp extension DLL
    The call to LoadLibrary(ext) failed with error 2.
    Please check your debugger configuration and/or network access
    Loaded exts extension DLL
    The call to LoadLibrary(uext) failed with error 2.
    Please check your debugger configuration and/or network access
    Loaded ntsdexts extension DLL
    Symbol search path is: *** Invalid *** : Verify _NT_SYMBOL_PATH setting
    Executable search path is:
    ModLoad: 00400000 0040c000   TRHistoryWnd.exe
    ModLoad: 7c900000 7c9af000   ntdll.dll
    ModLoad: 7c800000 7c8f6000   C:\WINDOWS\system32\kernel32.dll
    ModLoad: 61740000 617aa000   C:\WINDOWS\SYSTEM32\SYSFER.DLL
    ModLoad: 5b860000 5b8b5000   C:\WINDOWS\system32\NETAPI32.dll
    ModLoad: 77dd0000 77e6b000   C:\WINDOWS\system32\ADVAPI32.dll
    ModLoad: 77e70000 77f02000   C:\WINDOWS\system32\RPCRT4.dll
    ModLoad: 77fe0000 77ff1000   C:\WINDOWS\system32\Secur32.dll
    ModLoad: 77c10000 77c68000   C:\WINDOWS\system32\msvcrt.dll
    ModLoad: 10000000 10015000   D:\pcsnt\stdtrans42\bin\bctools.dll
    ModLoad: 00380000 0039b000   D:\pcsnt\stdtrans42\bin\dll_bccore.dll
    ModLoad: 76b40000 76b6d000   C:\WINDOWS\system32\WINMM.dll
    ModLoad: 77f10000 77f59000   C:\WINDOWS\system32\GDI32.dll
    ModLoad: 7e410000 7e4a1000   C:\WINDOWS\system32\USER32.dll
    ModLoad: 7c9c0000 7d1d7000   C:\WINDOWS\system32\SHELL32.dll
    ModLoad: 77f60000 77fd6000   C:\WINDOWS\system32\SHLWAPI.dll
    ModLoad: 10200000 10321000   C:\WINDOWS\WinSxS\x86_Microsoft.VC80.DebugCRT_1fc8b
    3b9a1e18e3b_8.0.50727.762_x-ww_5490cd9f\MSVCR80D.dll
    ModLoad: 003b0000 003bc000   D:\pcsnt\stdtrans42\bin\dll_bcmessage.dll
    ModLoad: 003d0000 003e4000   D:\pcsnt\stdtrans42\bin\dll_zlib.dll
    ModLoad: 00410000 00512000   C:\WINDOWS\WinSxS\x86_Microsoft.VC80.DebugCRT_1fc8b
    3b9a1e18e3b_8.0.50727.762_x-ww_5490cd9f\msvcm80d.dll
    ModLoad: 79000000 79046000   C:\WINDOWS\system32\mscoree.dll
    ModLoad: 76390000 763ad000   C:\WINDOWS\system32\IMM32.DLL
    ModLoad: 773d0000 774d3000   C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Cont
    rols_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll
    ModLoad: 5d090000 5d12a000   C:\WINDOWS\system32\comctl32.dll
    Access violation - code c0000005 (first chance)
    eax=00000000 ebx=003b5bf0 ecx=00000000 edx=00000000 esi=0012f3d8 edi=00000001
    eip=0038acd9 esp=0012e608 ebp=0012e618 iopl=0         nv up ei pl nz na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
    *** ERROR: Symbol file could not be found.  Defaulted to export symbols for D:\p
    csnt\stdtrans42\bin\dll_bccore.dll -
    dll_bccore!argcargv+19:
    0038acd9 8b1481           mov     edx,[ecx+eax*4]   ds:0023:00000000=????????
    0:000>

    The fuction I'm calling lives in bctools.dll.  It depends on others (I guess that's why they are being loaded) but no functions in the other dll's are begin called.

    It looks like the comctl32.dll in my \windows\system32 folder is being passed over for one in the \windows\SxS\... folder.  What is this folder?  Can I get rid of it?

    Thanks,
    Brian

    Tuesday, June 24, 2008 4:07 PM
  • I take that back, it looks like two versions are being loaded. One from the SxS folder and one from the system32 folder.  Could this be the problem?
    • Edited by EricksonBrian Tuesday, June 24, 2008 4:13 PM Mis-spelled word
    Tuesday, June 24, 2008 4:12 PM
  • That's not it.  It is dying in one of your homegrown DLLs, dll_bccore.  A function named argcargv(), sounds like a classic command line parsing utility function.  Can't say anything more sensible about it.
    Hans Passant.
    Tuesday, June 24, 2008 4:53 PM
    Moderator
  • Oops, your right...Thanks for pointing that out. 

    Here is the code:
    /*-----------------------------------------------------------------------  
     *  
     * Routine that returns the command line arguments of the process.  
     *  
     * (c) Copyright 2002 by Bauer Controls.  All rights reserved.  
     *  
     * $Header:   X:/PVCS/PCS/CORE/CORETOOL/argcargv.c_v   4.1.0.1   19 Oct 2004 09:59:56   Librarian  $  
     *  
     * $Log:   X:/PVCS/PCS/CORE/CORETOOL/argcargv.c_v  $  
     *  
     *    Rev 4.1.0.1   19 Oct 2004 09:59:56   Librarian  
     * No change.  
     *  
     *    Rev 4.1   19 Oct 2004 09:59:56   Librarian  
     * Initial 4.1  
     *  
     *    Rev 4.0.0.1   Jul 15 2003 10:03:38   Kevin  
     * No change.  
     *  
     *    Rev 4.0   Jul 15 2003 10:03:38   Kevin  
     * Initial 4.0  
     *  
     *    Rev 3.3.0.1   25 Dec 2002 11:28:48   Librarian  
     * No change.  
     *  
     *    Rev 3.3   25 Dec 2002 11:28:48   Librarian  
     * Initial 3.3  
     *  
     *    Rev 3.2.0.1   20 Dec 2002 14:35:44   gourlay  
     * No change.  
     *  
     *    Rev 3.2   20 Dec 2002 14:35:42   gourlay  
     * Initial 3.2  
     *  
     *-----------------------------------------------------------------------*/  
     
    #define  WIN32_LEAN_AND_MEAN  
    #include <windows.h> 
    #include <shellapi.h> 
    #include <stdlib.h> 
     
    #include "bcerr.h"  
    #include "bcstring.h"  
    #include "argcargv.h"  
     
     
    #define CMD_LINE_ARGS_MAX  10    /* maximum number of command line args */  
    #define CMD_LINE_ARGS_SIZE 2048  /* maximum size of command line args */  
     
    __declspec(thread) static int    argcnt = 0;                   /* number of args */  
    __declspec(thread) static char * argptr[CMD_LINE_ARGS_MAX];    /* pointers to args */  
    __declspec(thread) static char   argdata[CMD_LINE_ARGS_SIZE];  /* arg data */  
     
     
     
    /*----------------------------------------------------------------------  
     *  
     * argcargv -- Output the command line arguments of the current process.  
     *    This can be called at any time and as many times as desired during  
     *    the life of a PCS process.  The first time it's called it gets the  
     *    command line, parses the arguments, and outputs them as if they  
     *    were arguments to the standard main function.  If it's called  
     *    again it simply returns the same saved data.  
     *  
     *    To be consistent with Windows, this uses a Windows function  
     *    CommandLineToArgvW to parse the command line.  CommandLineToArgvW  
     *    only exists in a Unicode version, so we have to take the extra  
     *    step here of converting the results to single byte character  
     *    strings.  Although the command line is a process-wide property,  
     *    for simplicity this function repeats its parsing and saves the  
     *    data once for each thread.  
     *  
     * Returns:  
     *    PCS_SUCCESS on success.  
     *    PCS_INSUF_MEMORY if the command line arguments would overflow this  
     *       module's static buffers.  
     *  
     *----------------------------------------------------------------------*/  
     
    long argcargv  
    (  
       int *    argc,          /* (out) number of command line arguments */  
       char *** argv           /* (out) pointer to array of pointers to arguments */  
    )  
    {  
       long        rc = PCS_SUCCESS;    /* return code */  
       wchar_t **  w_argv;              /* Unicode arguments */  
       long        i;                   /* argument index */  
       size_t      args_size;           /* total size of arguments */  
     
     
       /* If the arguments haven't been parsed yet, do it.  
       */  
       if (argcnt == 0)  
       {  
          /* Parse the arguments into Unicode strings.  
          */  
          w_argv = CommandLineToArgvW (GetCommandLineW (), &argcnt);  
     
     
          /* If parsing was successful, check for sufficient buffer space, and  
          ** convert them to single byte character strings.  
          */  
          if (w_argv == NULL)  
          {  
             rc = PCS_INSUF_MEMORY;  
          }  
          else  
          {  
             /* If there aren't too many arguments, convert them to single byte  
             ** character strings, accumulate them in argdata, and save pointers  
             ** to them in argptr.  
             */  
             if (argcnt > (int) (sizeof argptr / sizeof argptr[0]))  
             {  
                rc = PCS_INSUF_MEMORY;  
             }  
             else  
             {  
                args_size = 0;  
                for (i = 0rc == PCS_SUCCESS && i < argcnt; i++)  
                {  
                   if (args_size >= sizeof argdata)  
                   {  
                      rc = PCS_INSUF_MEMORY;  
                   }  
                   else  
                   {  
                      argptr[i] = &argdata[args_size];  
                      wcstombs_copy (argptr[i], w_argv[i], sizeof argdata - args_size);  
                      args_size += wcslen (w_argv[i]) + 1;  
                   }  
                }  
             }  
     
             /* Free the memory allocated by CommandLineToArgvW.  
             */  
             (void) GlobalFree (w_argv);  
          }  
       }  
     
     
       /* Output the results  
       */  
       if (rc != PCS_SUCCESS)  
       {  
          argcnt = 0;  
       }  
       else  
       {  
          *argc = argcnt;  
          *argv = argptr;  
       }  
       return rc;  
    }  
     

    Since I didn't see any obvious bugs, I took out the __declspec(thread) definitions on the static variables and now everything 'seems' to work.  Can you help in figuring out why this might be?

    Thanks,
    Brian
    Tuesday, June 24, 2008 6:01 PM
  • __declspec(thread) declarators on variables have several draconian restrictions.  You've violated on of the rules spelled out in this MSDN library article.   There's no clean error detection either, just bam! AV. 
    Hans Passant.
    Tuesday, June 24, 2008 6:24 PM
    Moderator
  • Looking at the disassembled code we see:
       if (argcnt == 0)  
    0038ACCD  mov         eax,dword ptr [__tls_index (396C1Ch)]   
    0038ACD2  mov         ecx,dword ptr fs:[2Ch]   
    0038ACD9  mov         edx,dword ptr [ecx+eax*4]   
    0038ACDC  cmp         dword ptr [edx+0A98h],0   
    0038ACE3  jne         argcargv+1BDh (38AE7Dh)  
    This is the access violation because eax ends up with zero (null).  That means there is no thread local storage yet?

    We looked at the MSDN article but don't see where we are violating any rules.  Can you be more specific?

    Thanks,
    Brian
    Tuesday, June 24, 2008 7:04 PM
  • I'm fuzzy on your code and the details but LoadLibrary() is usually the neck-shot.  You'd have to explicitly call TlsAlloc().  There is also a limited number of thread local storage slots available, 64 if I'm not mistaken.  I don't know what happens when you ask for more, but looking at vc\crt\src\tidtable.c, I don't see it generate a nice exception, just return FALSE when TlsAlloc() fails.   Hmm, should fail the DLL load though...

    One thing I'd do is talk to your fellow devs and discuss if there is really a point in making command line arguments thread-local.  I don't see how you could ever have different threads having different .exe command line arguments.
    Hans Passant.
    Tuesday, June 24, 2008 8:03 PM
    Moderator
  • I've already modified the code to not require thread local storage.  Your right in that it's just not necessary here.  However, we do this kind of thing elsewhere where it is really necessary.  So, I'd like to understand.

    I've looked through the code for all the homegrown dll's involved, for this particular case, and there is no call to LoadLibrary.  So, I'm still curious about what TLS rule we're violating.
    Tuesday, June 24, 2008 8:28 PM
  • Hmya, you're a million miles closer to the real problem than you were 9 hours ago when you started the thread.  Why don't you poke it at for a while, I'm sure you'll find out what the real problem is.  Good luck.
    Hans Passant.
    • Proposed as answer by EricksonBrian Wednesday, June 25, 2008 10:53 AM
    • Unproposed as answer by EricksonBrian Wednesday, June 25, 2008 10:53 AM
    Tuesday, June 24, 2008 10:54 PM
    Moderator
  • True enough, and I've learned a lot as well.  Thanks for all your help.  If I find anything worthwhile, I'll post it back here...

    Brian
    Wednesday, June 25, 2008 10:54 AM