Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

application crash outside Visual Studio

Posted on 2003-11-19
8
Medium Priority
?
454 Views
Last Modified: 2013-11-20
hi,

i've developped an mfc application, which uses 2 external dlls (Xerces and curl) and an activeX control to access the local machine's WMI and produce a XML file with the information.
The application does it's stuff in a timer triggered loop, ie every 30 seconds or so it accesses some info via WMI.

Everything works fine when I run the app inside VS.NET (in both debug and release configs), but when i run the app outside the IDE, it crashes after the first loop (sometimes it goes for a few loops, sometimes just one).

All this in windows xp sp1.

All the memory leak detectors i've tried report no leaks.

When I JIT debug, I see that the crash happens on code that has worked on previous iterations, sometimes on the Xerces stuff, other times on my registry accessing functions (RegQueryValueEx, namely). I get a "Memory could not be read[/written] sometimes" error. I have looked in to some dynamic condition that would cause the error, but i can't get past the fact that all the iterations are exactly alike (same information retrieved over and over again) and the code works inside VS.NET (both configs).

All this happens only from the second iteration of the program onward. To my best knowledge, the registry related system calls are made as seen on the msdn sample code. xerces stuff is also very much like the samples (including cleanup stuff).

help much appreciated. thanks!

sopppas
0
Comment
Question by:sopppas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
8 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 9781957
>>Everything works fine when I run the app inside VS.NET

As you haven't posted any code: Check for uninitialized variables, especially pointers. The behaviour you described is typical for such small mistakes.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9785224
The difference in running application from VS and out of it is current directory. Maybe this can be a reason?
0
 

Author Comment

by:sopppas
ID: 9786114
hi,

AlexFM I've tried running the program inside the Debug|Release directory and in the project dir. No luck!

I'm gonna provide you with some code, then:

- the whole program is a systray application which, from time to time, iterates do find system info. This is done with the following loop:

void CEasyAppDlg::OnTimer (UINT TimerVal)
{
      KillTimer(timerId);

#ifdef _DEBUG
      CMemoryState oldMemState, newMemState, diffMemState;
      oldMemState.Checkpoint();
#endif
      
      CEasyApp::XMLCreate();
      

#ifdef _DEBUG
      newMemState.Checkpoint();
      if( diffMemState.Difference( oldMemState, newMemState ) )
    {
        TRACE( "Memory leaked!\n" );
            oldMemState.DumpStatistics();
    }
#endif

      timerId = SetTimer(IDT_TIMER_0, 1000, NULL); // 30 segundos
}

this function is also called when the program is first started, ie inside the OnInitDialog. As previously stated, no memory leaks are reported by CMemoryState.

- anyways, CEasyApp::XMLCreate is the core function of the program: it makes A LOT of wmi queries, a few registry ones, and uses xerces to create a XML file with the collected system info. These queries are made from within an ocx active X controller. The following are examples of how I'm doing this
 
      
      // inside XMLCREATE
      CString str;
      str = CagenteActXApp::getDomainAndName(); // the getDomainAndName function is in the ocx

      machineElem->setAttribute(X("id"), X(str)); // these are Xerces lib functions.
      ////////////////////////////


      // this function is defined in the ocx
      CString CagenteActXApp::getDomainAndName() {

      HRESULT hr;

      // Get list of objects
      CComPtr<IEnumWbemClassObject> spEnumInst;
      CComBSTR bstrQuery("SELECT * FROM Win32_ComputerSystem");

      hr = spServices->ExecQuery(CComBSTR(_T("WQL")), bstrQuery,
                  WBEM_FLAG_BIDIRECTIONAL, NULL, &spEnumInst); // some crashes occur in this line on the 2nd or 3rd iteration

      CComVariant varName, domain;
      bool bFinished = false;
      while (!bFinished)
      {
            ULONG uNumOfInstances = 0;
            CComPtr<IWbemClassObject> spInstance;
            HRESULT hrNext = spEnumInst->Next(10000, 1, &spInstance,
                  &uNumOfInstances);
            
            if (hrNext == WBEM_S_FALSE || uNumOfInstances == 0)
                  bFinished = true;
            else
            {
                  // Get properties from the object
                  hr = spInstance->Get(CComBSTR(_T("Name")), 0, &varName, 0, 0);
                  hr = spInstance->Get(CComBSTR(_T("Domain")), 0, &domain, 0, 0);
      
            }
      }

      BSTR bstr = V_BSTR(&domain);
      BSTR bstr2 = V_BSTR(&varName);
      
      CString cs(bstr);
      cs += "\\";
      CString cs2(bstr2);
      cs += cs2;
      
      VariantClear(&varName);
      VariantClear(&domain);

      return cs;  // returns something like WORKGROUP\MYCOMPUTER
      }
      /////////////////

      // again in XMLCreate;
      list<CString> propVal2;
      CagenteActXApp::getSoftwareSet(&propVal2); // this retrieves all the installed programs
      //////////////////////

      void CagenteActXApp::getSoftwareSet(std::list<CString> *res) {


      CHAR    swName[sizeof( DWORD ) * 1024] = ""; // Buffer for class name.


      HKEY hKey;
      HKEY hKeyRoot;

      hKeyRoot = HKEY_LOCAL_MACHINE;

      HRESULT retCode;

      retCode = RegOpenKeyEx (hKeyRoot,
                            "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
                            0,
                            KEY_ALL_ACCESS,
                            &hKey);

      list<char *> keys;
      HRESULT hr = 0;
      int j = 0;
      while(hr != ERROR_NO_MORE_ITEMS) {
            DWORD dwSize = sizeof( DWORD ) * 1024;
            swName[0] = '\0';
            rucucu = RegEnumKeyEx(
                                    hKey,         // handle of key to enumerate
                                    j,            // index of subkey to enumerate
                                    swName,         // address of buffer for subkey name
                                    &dwSize,         // address for size of subkey buffer
                                    NULL,         // reserved
                                    NULL,         // address of buffer for class string
                                    0,            // address for size of class buffer
                                    NULL          // address for time key last written to
                                    );
            keys.push_back(strdup(swName));
            j++;
      }

      while(!keys.empty()) {
            TCHAR skey[sizeof(DWORD)*1024];
            DWORD dwSize = sizeof( DWORD ) * 1024;
            strcpy(skey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\0");
            strcat(skey, "\\");
            strcat(skey, keys.front());
            strcat(skey, "\0");
            delete keys.front();
            keys.pop_front();
            HKEY hKey2;

            retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
                            skey,
                            0,
                            KEY_ALL_ACCESS,
                            &hKey2);

            skey[0] = '\0';

            retCode = RegQueryValueEx(hKey2, "DisplayName", 0, NULL, NULL, &dwSize ); // it's been known to crash here
            retCode = RegQueryValueEx(hKey2, "DisplayName", 0, NULL, (BYTE *)&skey, &dwSize );
            if(skey[0] == '\0') {
                  dwSize = sizeof( DWORD ) * 1024;
                  retCode = RegQueryValueEx(hKey2, "Display Name", 0, NULL, NULL, &dwSize );
                  retCode = RegQueryValueEx(hKey2, "Display Name", 0, NULL, (BYTE *)&skey, &dwSize );
            }
            if(skey[0] == '\0') {
                  dwSize = sizeof( DWORD ) * 1024;
                  retCode = RegQueryValueEx(hKey2, "QuietDisplayName", 0, NULL, NULL, &dwSize );
                  retCode = RegQueryValueEx(hKey2, "QuietDisplayName", 0, NULL, (BYTE *)&skey, &dwSize );
            }

            strcat(skey, "\0");
            if(skey[0] != '\0'){
                  res->push_back(skey);
            }
            
            RegCloseKey (hKey2);

      }

      RegCloseKey (hKey);
      }
      
I think this illustrates how must of it is being done...
Thanks for the suggestions so far.
s
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 1

Expert Comment

by:bearcrsw
ID: 9805836
A couple of bits which look dubious are

     HRESULT hr = 0;
     int j = 0;
     while(hr != ERROR_NO_MORE_ITEMS) {
          DWORD dwSize = sizeof( DWORD ) * 1024;
          swName[0] = '\0';
          rucucu = RegEnumKeyEx(
                              hKey,         // handle of key to enumerate
                              j,            // index of subkey to enumerate
                              swName,         // address of buffer for subkey name
                              &dwSize,         // address for size of subkey buffer
                              NULL,         // reserved
                              NULL,         // address of buffer for class string
                              0,            // address for size of class buffer
                              NULL          // address for time key last written to
                              );
          keys.push_back(strdup(swName));
          j++;
     }

the swName is pushed onto list even if RegEnumKeyEx failed.
also hr does not ppear to be changed, as rucucu is the return value, also what about errors other than NO_MORE _ITEMS .

also on the

retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
                            skey,
                            0,
                            KEY_ALL_ACCESS,
                            &hKey2);

the retVal is  not checked. Which could lead to problems with the RegQueryValueEx
0
 

Author Comment

by:sopppas
ID: 9809462
Hi everyone,

I've got it! Don't really know what was wrong, but it seems to be working now.

this code doen't work:

        CComVariant varName;
      bool bFinished = false;
      while (!bFinished)
      {
            ULONG uNumOfInstances = 0;
            CComPtr<IWbemClassObject> spInstance = 0;
            HRESULT hrNext = spEnumInst->Next(10000, 1, &spInstance,
                  &uNumOfInstances);
      
            if (hrNext == WBEM_S_FALSE || uNumOfInstances == 0) // jit debug often indicated a crash right here
                  bFinished = true;
            else
            {
 (...)

and this does:

bool bFinished = false;
      while (!bFinished)
      {
            // Get the instance
            ULONG uNumOfInstances = 0;
            CComPtr<IWbemClassObject> spInstance;
            HRESULT hrNext = spEnumInst->Next(10000, 1, &spInstance,
            &uNumOfInstances);
 
            if (hrNext == WBEM_S_FALSE)
                  bFinished = true;
            else if (hrNext == WBEM_S_NO_ERROR)
            {

I can't really tell where exactly the error is, but maybe the result is sometimes an error code other than WBEM_S_FALSE, causing the problem.
Anyway, thanks  bearcrsw for the tips (I'm gonna use them anyway), and thanks to everyone else who took the time to respond to this cry for help!

s
0
 
LVL 1

Accepted Solution

by:
Computer101 earned 0 total points
ID: 11984792
PAQed, with points refunded (500)

Computer101
E-E Admin
0

Featured Post

Will your db performance match your db growth?

In Percona’s white paper “Performance at Scale: Keeping Your Database on Its Toes,” we take a high-level approach to what you need to think about when planning for database scalability.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question