• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1619
  • Last Modified:

Unhandled error when exiting an DLL which grabs data from a database and store data into an array of structure

Hi,

Here's what I did.
I declared a structure for holding data:

#define LEN_DATA 100

struct DB_DATA
{
      char m_Username[LEN_DATA];
      char m_Password[LEN_DATA];
      char m_Submit[LEN_DATA];
};

DB_DATA* p_DBData = new DB_DATA;

Then I have 2 DLL functions for constructing and destroying the array:

BOOL EXPORTED_DLL_FUNCTION ConstructUserArray()
{

(codes ommited for database connection.. )

      SDWORD cb;
      char szUsername[LEN_DATA];
      char szPassword[LEN_DATA];
      char szSubmit[LEN_DATA];

      SQLBindCol(h_stmt, 1, SQL_C_CHAR, szUsername, LEN_DATA, &cb);
      SQLBindCol(h_stmt, 2, SQL_C_CHAR, szPassword, LEN_DATA, &cb);
      SQLBindCol(h_stmt, 3, SQL_C_CHAR, szSubmit, LEN_DATA, &cb);

      rc = SQLFetch(h_stmt);

      m_NumRecord = 0;

      while (SQL_SUCCESS == rc)
      {
            strcpy(p_DBData[m_NumRecord].m_Username, szUsername);
            strcpy(p_DBData[m_NumRecord].m_Password, szPassword);
            strcpy(p_DBData[m_NumRecord].m_Submit, szSubmit);
            m_NumRecord++;

            rc = SQLFetch(h_stmt);
      }

(codes ommited for database disconnection.. )
}

BOOL EXPORTED_DLL_FUNCTION DestroyUserArray()
{
      for (int i=0; i<sizeof(p_DBData); i++){
            p_DBData[i].m_Username[0] = 0;
            p_DBData[i].m_Password[0] = 0;
            p_DBData[i].m_Submit[0] = 0;
      }
      return true;
}

The error was generated when I was exiting the DLL.. here's what I saw from the Call Stack:

>      mfc71d.dll!CThreadSlotData::GetThreadValue(int nSlot=2012648534)  Line 269      C++

with the code:
inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
      EnterCriticalSection(&m_sect);
      ASSERT(nSlot != 0 && nSlot < m_nMax);
      ASSERT(m_pSlotData != NULL);
      ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);
      ASSERT(m_tlsIndex != (DWORD)-1);
      if( nSlot <= 0 || nSlot >= m_nMax ) // check for retail builds.
      {
            LeaveCriticalSection(&m_sect);
            return NULL;
      }

      CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);
      if (pData == NULL || nSlot >= pData->nCount)
      {
            LeaveCriticalSection(&m_sect);
            return NULL;
      }
      void* pRetVal = pData->pData[nSlot];
      LeaveCriticalSection(&m_sect);
      return pRetVal;      <------------------------------------------- Line 269
}

I tried to free the variables szUsername, szPassword, szSubmit right after the while loop but then it generates the error at the end of the free() function..

Any help is greatly appreciated..

Thanks a lot.
0
ewong_111
Asked:
ewong_111
  • 4
  • 3
1 Solution
 
nonubikCommented:
>I tried to free the variables szUsername, szPassword, szSubmit right after the while loop but then it generates the error at the end of the free() function..

There is no need for that, they are staticaly allocated, so you don't need to free them.

As for your problem, try to pass the void * as parameter, not to return it:

inline void CThreadSlotData::GetThreadValue(int nSlot, void *pRetVal)
{
...
   pRetVal = pData->pData[nSlot];
    LeaveCriticalSection(&m_sect);

}
0
 
jkrCommented:
>>mfc71d.dll!CThreadSlotData::GetThreadValue(int nSlot=2012648534)

Isn't 2012648534 a quite huge value? BTW, when exactly is that function being called? The TLS slot might be gone once the thread detaches.

0
 
ewong_111Author Commented:
nonubik,

The point is, the CThreadSlotData::GetThreadValue function is in the mfc71d.dll (I assumed) that I am checking the Call stack and see that it hangs there, not that I wrote the function myself and have a control of what to do with it or what valuable I can pass to it.
As I said, my program used an DLL and it works just fine before I exit it. I used a dialog based program to access the DLL and the error was generated when I click on "Cancel" which is to exit the DLL.

ewong_111
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
ewong_111Author Commented:
jkr,

The DLL has another function which set up a hook for monitoring keystrokes and mouse actions.
I am not sure when the CThreadSlotData::GetThreadValue is called, but I "feel" like it is somewhere when my DLL Client program (dialog based) is terminating the DLL.
In addition, the array of structure is used to compare the keystokes with the values in the database.. not sure if this help..
Thanks a lot.

ewong_111
0
 
ewong_111Author Commented:
Hi,

I tried to change the functions to virtual functions:

class KeyApp : public CWinApp
{
public:
      KeyApp();

// Overrides
public:
      virtual BOOL InitInstance();
      virtual BOOL ExitInstance();
      virtual BOOL ConstructUserArray();
      virtual BOOL DestroyUserArray();

      DECLARE_MESSAGE_MAP()
};

and called the ConstructUserArray() in InitInstance():

BOOL CKeyApp::InitInstance()
{
      ConstructUserArray();
      AFX_MANAGE_STATE(AfxGetStaticModuleState());
      g_hInstance = AfxGetInstanceHandle();
      return TRUE;
}

and the DestroyUserArrar() in ExitInstance():

int CGCRCoKeyApp::ExitInstance()
{
      ExitHook();
      DestroyUserArray();
      return CWinApp::ExitInstance();
}

and now I get the error code in the free() function:
>      msvcr71.dll!free(void * pBlock=0x003745e8)  Line 103      C

#ifdef _MT
            }
            __finally {
                _munlock(_HEAP_LOCK );
            }
#endif  /* _MT */

            if (pmap == NULL)
                HeapFree(_crtheap, 0, pBlock);
        }
#endif  /* CRTDLL */
        else    //  __active_heap == __SYSTEM_HEAP
#endif  /* _WIN64 */
        {
            HeapFree(_crtheap, 0, pBlock);
        }
} <------------------------------------------------ Line 103

jkr, I think your direction is correct, somehow the TLS slot was gone before the thread detaches.. but what did I do to cause that happen?

Thanks a lot..

ewong_111
0
 
jkrCommented:
Do you have a 'DllMain()' where you can monitor DLL_THREAD_DETACH? That's the time to discard the slot.
0
 
ewong_111Author Commented:
jkr,

no, I don't have a DllMain(), but I guess it's time for me to build it.. would you please give me a little hint on what to do to discard the slot in there?
Thank you so much.

ewong_111
0
 
jkrCommented:
I don't know the class you are using, but it'd be something like

// DllMain() is the entry-point function for this DLL.
BOOL
WINAPI
DllMain ( HINSTANCE, DWORD dwReason, LPVOID lpvReserved) {


    switch ( dwReason) {
 
        // The DLL is loading due to process
        // initialization or a call to LoadLibrary.
 
        case DLL_PROCESS_ATTACH:

            // Allocate a TLS index.
 
            if ( 0xFFFFFFFF == ( dwTlsIndex = TlsAlloc ())) {

                return FALSE;
            }

        // No break: Initialize the index for first thread.
 
        // The attached process creates a new thread.
 
        case DLL_THREAD_ATTACH:
 
            // Initialize the TLS index for this thread.
 
            TlsSetValue ( dwTlsIndex, <some pointer value>);
            break;
 
        // The thread of the attached process terminates.
 
        case DLL_THREAD_DETACH:
 
            TlsSetValue ( dwTlsIndex, NULL);
            break;
 
        // DLL unload due to process termination or FreeLibrary.
 
        case DLL_PROCESS_DETACH:

            TlsFree ( dwTlsIndex);
            break;
 
        default:
            break;
    }
 
    return TRUE;
}
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now