DLL call sometimes works, sometimes crashes

Hi, I have a question about a dynamically loaded library I am using. I have called it SqlWrite, it is for connecting and writing to a Microsoft SQL server DB. I have a function in it that is defined as:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
extern "C" {
	__declspec(dllexport) RETCODE __cdecl SqlExecS(SQLHANDLESTR* h, LPCSTR Statement)
	{
		RETCODE     RetCode;

		std::string input = Statement;
		std::wostringstream conv;
		conv << input.c_str();
		std::wstring wCmd(conv.str());
		WCHAR* wCCmd = const_cast<WCHAR*>(wCmd.c_str());


		_setmode(_fileno(stdout), _O_WTEXT); // MSVC's special needs


		std::wcout << "exec " << wCCmd;
		RetCode = SQLExecDirect(h->hStmt,wCCmd, SQL_NTS);
		std::wcout << " retcode " << RetCode << std::endl;
		std::wcout << std::endl << "RETURNING FROM EXECSP NOW!!! " << std::endl;
		return RetCode;
	}
}



I then load it in another MSVC project as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	#ifdef WIN32//				C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\GetPageSource\\Debug\\GetPageSource.dll
		#pragma message("WIN32 is defined")
		#ifdef _DEBUG	
			SetErrorMode(0);
			HINSTANCE hGetProcIDDLLGSP = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\GetPageSource\\Debug\\GetPageSource.dll");
			HINSTANCE hGetProcIDDLLREGEX = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\regex\\Debug\\regex.dll");
			HINSTANCE hGetProcIDDLLSQLWRITE = LoadLibrary(L"C:\\Users\\a\\Documents\\visual studio 2012\\Projects\\SQLWrite\\Debug\\SQLWrite.dll");
		#else
			#ifdef NDEBUG
				SetErrorMode(0);
				HINSTANCE hGetProcIDDLLGSP = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\GetPageSource\\Release\\GetPageSource.dll");
				HINSTANCE hGetProcIDDLLREGEX = LoadLibrary(L"C:\\Users\\a\\Documents\\Visual Studio 2012\\Projects\\regex\\Release\\regex.dll");
				HINSTANCE hGetProcIDDLLSQLWRITE = LoadLibrary(L"C:\\Users\\a\\Documents\\visual studio 2012\\Projects\\SQLWrite\\Release\\SQLWrite.dll");
			#endif
		#endif
	#endif
#endif


. then I prototype it as:
1
2
3
4
5
6
7
8
9
10
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLLSQLWRITE),"SqlExecS"); 
	std::cout << GetLastError() << std::endl;
    /* 
       Define the Function in the DLL for reuse. This is just prototyping the dll's function.  
    */ 
    typedef RETCODE (__cdecl * pICFUNCSqlExecS)(SQLHANDLESTR* h, LPCSTR Statement);

    pICFUNCSqlExecS SqlExecSP; 
    SqlExecSP = pICFUNCSqlExecS(lpfnGetProcessID);



And, finally, I use it as, for example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SQLHANDLESTR * h = SqlConnectDBP();

if(h)
{

          std::string comGP = std::string("SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = '");
	comGP.append(plaDa->at(i).plName);
	comGP.append("' AND FirstName = '");
	comGP.append(plaDa->at(i).pfName);
	comGP.append("'");
			
	LPCSTR Statement = comGP.c_str();


	SqlExecSP(h,Statement);

}

As you can see, inside the prototyped function "SqlExecSP", I cout (or, rather, wcout for wide characters) the sql statement i am running, and the return code of the sql statement. a sql return code of "0" is equivalent to "SQL_SUCCESS". Then, I cout " got player again " after executon of SqlExecSP alias SqlExecS.

This usually works, and gives me following sample output:

1
2
3
4
exec SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = 'Abdellaoue' AND FirstName = 'Mohammed' retcode 0

RETURNING FROM EXECSP NOW!!!
 got player again


However, sometimes, the program, for some reason that I have no idea why, crashes somewhere between outputting "RETURNING FROM EXECSP NOW!!!" and outputting " got player again ", i.e. the output is then:
1
2
3
exec SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = 'Abdellaoue' AND FirstName = 'Mohammed' retcode 0

RETURNING FROM EXECSP NOW!!!

As you can see, it doesn't output the next line " got player again ", because it somehow crashes in between.


However,t he only line that should be executed between this, as far as I can understand, is the actual return of the DLL function SqlExecS, prototyped as SqlExecSP in my calling code, i.e. the only line that should be executed in between is:

return RetCode;

However, somehow, this fails, even though RetCode is "0", as I can see at the end of the output
 
exec SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = 'Abdellaoue' AND FirstName = 'Mohammed' retcode 0

Now, I have no idea why sometimes this crashes, and sometimes this works. I.e, I can sometimes call this function x times, and it doesnt fail, outputting " got player again " right after the calls, and sometimes, it fails somewhere in between, at call x, y, or z, i.e. sometimes i can execute it ten times successfully and sometimes i can't, even though the return code is still 0, and it just fails somewhere in between, and I have no idea why. I am not sure if it has to do with the call being a call to a dynamically loaded DLL function, but I can't see where else the error is.


Does anyone have ANY idea why this can be failing, and at different, seemingly random times?


Thanks for any input and help!!! :)


hansaaa :)
Last edited on
That first function, why to you have:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
extern "C" {
	__declspec(dllexport) RETCODE __cdecl SqlExecS(SQLHANDLESTR* h, LPCSTR Statement)
	{
		RETCODE     RetCode;

		std::string input = Statement;
		std::wostringstream conv;
		conv << input.c_str();
		std::wstring wCmd(conv.str());
		WCHAR* wCCmd = const_cast<WCHAR*>(wCmd.c_str());


		_setmode(_fileno(stdout), _O_WTEXT); // MSVC's special needs


		std::wcout << "exec " << wCCmd;
		RetCode = SQLExecDirect(h->hStmt,wCCmd, SQL_NTS);
		std::wcout << " retcode " << RetCode << std::endl;
		std::wcout << std::endl << "RETURNING FROM EXECSP NOW!!! " << std::endl;
		return RetCode;
	}
}

when this would do?
1
2
3
4
5
6
extern "C" {
	__declspec(dllexport) RETCODE __cdecl SqlExecS(SQLHANDLESTR* h, LPCSTR Statement)
	{
		return SQLExecDirect(h->hStmt,w Statement, SQL_NTS);
	}
}
I know you want logging, but there's a lot more noise than necessary.

LoadLibrary returns an HMODULE, you shouldn't need that cast in GetProcAddress().

You're passing in a narrow string into something that requires a wide string. If you code was a little cleaner, the compiler would do the type checking for you.

Cleaner?
You need a prototype for that function. Declare this in the DLL and include it in your app.
1
2
3
4
extern "C"
{
RETCODE __cdecl SqlExecS_Type(SQLHANDLESTR* h, LPCSTR Statement);
}


Then make the do GetProcAddress() like this.
 
SqlExecS_Type* SqlExecSP = (SqlExecS_Type*)GetProcAddress(hGetProcIDDLLSQLWRITE, "SqlExecSP");


Then call it like this:
1
2
3
4
5
6
7
8
9
if (SQLHANDLESTR* h = SqlConnectDBP())
{
	std::wstring comGP = L"SELECT [PlayerID], [FirstName], [LastName], [TeamID] FROM [soccer].[dbo].[Players] WHERE LastName = '";
	comGP.append(plaDa->at(i).plName);
	comGP.append(L"' AND FirstName = '");
	comGP.append(plaDa->at(i).pfName);
	comGP.append(L"'");
	SqlExecSP(h, comGP.c_str());
}


Also, you can consider _DEBUG and NDEBUG mutually exclusive. In fact one is redundant. _DEBUG is the Microsoft way, NDEBUG is the ANSI way. Choose one, but don't use both.

That would allow you to just do: #if ... #else ... #endif. It looks a little nicer and doesn't have the whole that your one does.

Also, make sure the Unicode settings are the same on both projects or the prototype won't catch your error due to the nature of that LPTCSTR morphing thing.
Last edited on
I don't see how any of that has anything to do with the errors I am getting, but I tried it anyway. no change ...
did you fix the unicode settings?
Have you used any casts?
Where does the application crash?
Topic archived. No new replies allowed.