Thread: Random crashes? huh?

  1. #1
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545

    Random crashes? huh?

    I can't seem to find out why my code is crashing randomly.
    I've got 2 projects in VC++ 2005.
    One builds a DLL which just exports some functions that take a pointer to a struct and return unsigned int. Right now all they do is print out all the data in the struct to a file.

    The other project is a console app that loads the DLL & calls whatever function I want in the DLL. I have a text menu with options to Load/Unload the DLL, and call each function...

    Sometimes when I press 'L' to load the DLL it says it fails to load the DLL, but most times it loads fine.
    Sometimes when I press a number to call an exported function it will crash (even the catch(...) handlers don't help), but other times the function runs just fine.

    Sometimes is crashes the very first time I run a function, and other times I can run the same function 10 times before it crashes.

    How the hell do I debug this mess?
    What are the most likely causes of this type of random crashing behavior? Stack corruption or something?

    EDIT: I also get a bunch of "TestHarness.exe has triggered a breakpoint" messages, but if I break there it just drops me somewhere deep inside the CRT code.
    Last edited by cpjust; 07-07-2008 at 01:53 PM.

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    I think we might need an example. The fact it may load or not load the DLL is a little odd imo. There appears to be something fundamentally wrong with your situation, possibly something basic.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Here are some random thoughts about random crashes :-) Check for any or all of the following:

    - uninitialized pointer
    - double deleting a pointer
    - buffer overrun
    - issues with order of initialization of statics
    - shallow copy when you wanted deep copy

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I think I've narrowed it down to the code that causes the crash, but I still don't see what's wrong.
    Code:
    Tstring
    ToStr( DWORD  num )
    {
    	std::basic_stringstream<TCHAR> ss;
    	ss << num;
    	Tstring ret;
    	ss >> ret;
    	return ret;
    }
    
    
    void
    FillArgList( std::vector<Tstring>&  argList,
    			EXIT_DSECT*  dsect )
    {
    	try
    	{
    		argList.push_back( _T( "EXIT_NUMBER:" ) );
    		Tstring strTemp = ToStr( dsect->EXIT_NUMBER );
    		argList.push_back( strTemp );
    		argList.push_back( _T( "EXIT_INIT_COMPUTER_NAME:" ) );
    		argList.push_back( dsect->EXIT_INIT_COMPUTER_NAME );
    ...
    	}
    	catch( std::bad_alloc&  e )
    	{
    		std::cout << "Caugt a bad_alloc!  " << e.what() << std::endl;
    	}
    	catch( ... )
    	{
    		std::cout << "Caugt an unhandled exception!" << std::endl;
    	}
    }
    If I comment out the lines in red it doesn't crash.
    Tstring is a typedef for std::basic_string<TCHAR>

    Although, even when I comment out the lines above, I still catch bad_alloc exceptions randomly, but it doesn't crash.

  5. #5
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Can FillArgList() ever be called with dsect being set to NULL?

  6. #6
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by MacGyver View Post
    Can FillArgList() ever be called with dsect being set to NULL?
    That's my thought. dsect is null or pointing somewhere unexpected.

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by MacGyver View Post
    Can FillArgList() ever be called with dsect being set to NULL?
    No, I always pass the address of a local struct. I don't do any memory allocation of my own.
    It would blow up on one of the lines below the commented out lines if that was the case.

    The dsect struct has TCHAR strings and DWORD numbers in it. Only the lines where I call ToStr() on the DWORDS are what blows up (sometimes).

  8. #8
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    OK, I've refined the crash even farther. If I leave the other lines uncommented but comment out these lines (in red) it gives me the occasional bad_alloc, but no crash:
    Code:
    Tstring
    ToStr( DWORD  num )
    {
    	std::basic_stringstream<TCHAR> ss;
    	ss << num;
    	Tstring ret;
    	ss >> ret;
    	return ret;
    }
    I've tried building in UNICODE and ASCII and get the same problems either way.
    The value of num is the same. I keep calling it with the same value and most times it works, sometimes it throws bad_alloc, and other times it crashes.

    I think the crash happens just after the FillArgList() function returns.

    BTW, the dsect local variable is created in the .exe and its address is passed to the DLL function where the code above lives.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    it's hard to say without seeing more code, but most of the problems I've seen are caused by either binary incompatibility or mismatched calling conventions. in the first case just remember to always specify a byte padding boundary for structures and avoid interfacing with non-pod types (ie: std::string, et al) like the plague. in the second case (which isn't really an issue unless you're using GetProcAddress) just be careful that the function pointer is defined with the same calling convention as the library routine.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Sebastiani View Post
    it's hard to say without seeing more code, but most of the problems I've seen are caused by either binary incompatibility or mismatched calling conventions. in the first case just remember to always specify a byte padding boundary for structures and avoid interfacing with non-pod types (ie: std::string, et al) like the plague. in the second case (which isn't really an issue unless you're using GetProcAddress) just be careful that the function pointer is defined with the same calling convention as the library routine.
    Actually, I am using GetProcAddress(). Should I be using something else instead?

    In .exe:

    Code:
    unsigned int
    RunXINIT( HMODULE hDLL )
    {
    	try
    	{
    		pXINIT pFunc = (pXINIT)GetProcAddress( hDLL, "XINIT" );
    
    		if ( pFunc == NULL )
    		{
    			PrintError( "Error running XINIT()!" );
    			return 0;
    		}
    
    		EXIT_INITTERM_DSECT dsect;
    		GetEXIT_INITTERM_DSECT( dsect );  // Populate dsect with some data.
    		return (pFunc)( &dsect );  // Calls XINIT() in the DLL.
    	}
    	catch( ... )
    	{
    		cout << "Caught an unhandled exception!" << endl;
    		PrintMsg( " " );
    		return 0;
    	}
    }
    In DLL:

    unsigned int
    Code:
    XINIT( EXIT_INITTERM_DSECT*  dsect )
    {
    	try
    	{
    		TRACE( "*** XINIT() ***" );
    
    		if ( dsect == NULL )
    		{
    			return 1;
    		}
    
    		unsigned int rc = EXIT_SUCCESS;
    		std::vector<Tstring> argList;
    
    		argList.push_back( _T( "==============================  XINIT()  ==============================" ) );
    		FillArgList( argList, dsect );
    
    		CUExit::CallScript( argList );  // Calls system() with a .bat file & all args concatenated together.
    		return rc;
    	}
    	catch( std::bad_alloc&  e )
    	{
    		std::cout << "Caught a bad_alloc in XINIT()!" << e.what() << std::endl;
    	}
    	catch( ... )
    	{
    		std::cout << "Caught an unhandled exception in XINIT()!" << std::endl;
    		getch();
    	}
    
    	return 1;
    }

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    If it's not valid for dsect to be NULL then it should be passed by reference instead.

    What is a Tstring? Is that something you made yourself? If so, my money's on the problem being in that.

    "caught" is spelt with an h
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Code:
    EXIT_INITTERM_DSECT dsect;
    GetEXIT_INITTERM_DSECT( dsect );  // Populate dsect with some data.
    I'm guessing dsect is being passed by reference here or it's really a macro of some sort. Otherwise, this is kind of pointless.

    Is pXINIT typedef'ed as this:

    Code:
    typedef unsigned int (*pXINIT)(EXIT_INITTERM_DSECT*);

  13. #13
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by iMalc View Post
    If it's not valid for dsect to be NULL then it should be passed by reference instead.

    What is a Tstring? Is that something you made yourself? If so, my money's on the problem being in that.

    "caught" is spelt with an h
    The DLL functions are extern "C" functions, so that part has to pass by pointers.
    Code:
    typedef std::basic_string<TCHAR>	Tstring;

    Quote Originally Posted by MacGyver View Post
    Code:
    EXIT_INITTERM_DSECT dsect;
    GetEXIT_INITTERM_DSECT( dsect );  // Populate dsect with some data.
    I'm guessing dsect is being passed by reference here or it's really a macro of some sort. Otherwise, this is kind of pointless.

    Is pXINIT typedef'ed as this:

    Code:
    typedef unsigned int (*pXINIT)(EXIT_INITTERM_DSECT*);
    Yes, GetEXIT_INITTERM_DSECT() takes a reference to dsect, and that's the typedef I'm using for the DLL function pointer.
    Code:
    #ifdef _UNICODE
    #  define Strncpy_s		wcsncpy_s
    #else
    #  define Strncpy_s		strncpy_s
    #endif
    
    void
    GetEXIT_INITTERM_DSECT( EXIT_INITTERM_DSECT&  dsect )
    {
    	dsect.EXIT_EXIT_NUMBER			= 1;
    	Strncpy_s( dsect.EXIT_INIT_COMPUTER_NAME,	(sizeof(dsect.EXIT_INIT_COMPUTER_NAME) / sizeof(TCHAR)),
    		_T("Computer_Name"),			(sizeof(dsect.EXIT_INIT_COMPUTER_NAME) / sizeof(TCHAR)) );
    	Strncpy_s( dsect.EXIT_MESSAGE,			(sizeof(dsect.EXIT_MESSAGE) / sizeof(TCHAR)),
    		_T("Message"),				(sizeof(dsect.EXIT_MESSAGE) / sizeof(TCHAR)) );
    	dsect.EXIT_RETURN_CODE			= 2;
    	dsect.EXIT_USER_FULLWORD		= 3;
    	dsect.EXIT_VERSION			= 4;
    }

  14. #14
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I'm thinking there must be a connection between the random crashes and the bad_alloc's being thrown... If I remove all the vector.push_back() calls I don't get any bad_alloc's anymore. I tried changing to const TCHAR* instead of Tstrings and allocating/deallocating memory myself, but I got a bad_alloc when trying to allocate just 11 bytes (then it works fine the next time...).

    Another strange thing is that sometimes when LoadLibrary() fails I get "One or more arguments are invalid", and other times I get "A dynamic link library (DLL) initialization routine failed."
    Last edited by cpjust; 07-08-2008 at 12:54 PM.

  15. #15
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Sounds like something might be wrong with your strings then, although I don't see anything wrong off hand. For LoadLibrary() to fail arbitrarily, there's got to be something seriously wrong that you're missing.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. random to int?
    By psyadam in forum C# Programming
    Replies: 7
    Last Post: 07-22-2008, 08:09 PM
  2. Lesson #3 - Math
    By oval in forum C# Programming
    Replies: 2
    Last Post: 04-27-2006, 08:16 AM
  3. Another brain block... Random Numbers
    By DanFraser in forum C# Programming
    Replies: 2
    Last Post: 01-23-2005, 05:51 PM
  4. How do I restart a random number sequence.
    By jeffski in forum C Programming
    Replies: 6
    Last Post: 05-29-2003, 02:40 PM
  5. Best way to generate a random double?
    By The V. in forum C Programming
    Replies: 3
    Last Post: 10-16-2001, 04:11 PM