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

x
?
Solved

Problems assigning memory

Posted on 1999-07-23
10
Medium Priority
?
236 Views
Last Modified: 2010-04-02
Hi.. I'm programming a dialog box to choose a directory. I have some problems on assigning memory...

In some part of the program I have the following method (pay atention in the while loop) :

void TBrowserDlg::FillTreeView( LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent )
{
  TV_ITEM tvi;
  TV_INSERTSTRUCT tvins;
  HTREEITEM hPrev = NULL;
  LPENUMIDLIST lpe = NULL;
  LPITEMIDLIST lpi = NULL, lpifqThisItem = NULL;
  LPTVITEMDATA lptvid;
  LPMALLOC lpMalloc;
  HRESULT Resultado;
  HWND hWnd = Arbol->GetParent( );
  ULONG ulFetched;
  char szBuff[MAX_PATH];

  Result = ::SHGetMalloc( &lpMalloc );
  if( SUCCEEDED( Result ) ) {
    Result = lpsf->EnumObjects( hWnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &lpe );
    if( SUCCEEDED( Result ) )
    {
      while( lpe->Next( 1, &lpi, &ulFetched ) == S_OK ) {

        lpMalloc->Free( lpi );
        lpi = 0;
      } // while
    }
  }
  else
    return;
  if( lpe )
    lpe->Release( );
  if( lpi && lpMalloc )
    lpMalloc->Free( lpi );
  if( lpifqThisItem && lpMalloc )
    lpMalloc->Free( lpifqThisItem );
  if( lpMalloc )
    lpMalloc->Release( );
}

I have isolated this loop because I found that in this part is a problem... If I run this program, when I close it, the program crashes, obligating me to reboot the computer... when I comment out that loop, the program works, that is, when I finish it, it closes well, without crashing.

Who can help me in this? do you have a Class to choose a directory? (I have to be able to choose from network neighborhood too, besides local disks, so I have to find the items starting from the desktop)

I'm using Borland C++ 5.0

Thanks in advance
0
Comment
Question by:demarcy
[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
  • 5
  • 5
10 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 600 total points
ID: 1200931
To be honest, I can't see a problem in the loop - if you want to pick a folder, you could simply use the following code:

 LPMALLOC    pMalloc;    /* Gets the Shell's default allocator */

    if  (   ::SHGetMalloc   (   &pMalloc)   ==  NOERROR)
        {
            BROWSEINFO      bi;
            char            pszBuffer   [   MAX_PATH];
            LPITEMIDLIST    pidl;

            // Get help on BROWSEINFO struct - it's got all the bit settings.
            bi.hwndOwner        =   hWnd;
            bi.pidlRoot         =   NULL;
            bi.pszDisplayName   =   pszBuffer;
            bi.lpszTitle        =   _T("Select a target Directory");
            bi.ulFlags          =   BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
            bi.lpfn             =   NULL;
            bi.lParam           =   0;

            // This next call issues the dialog box.
            if  (   pidl    =   ::SHBrowseForFolder (   &bi))
                {
                    if  (   ::SHGetPathFromIDList   (   pidl, pszBuffer))
                        {
                            // At this point pszBuffer contains the selected path */.
                        }

                    // Free the PIDL allocated by SHBrowseForFolder.
                    pMalloc->Free   (   pidl);
                }

            // Release the shell's allocator.        
            pMalloc->Release();    
        }   
0
 

Author Comment

by:demarcy
ID: 1200932
I have tested your solution and I have concluded that is a BC++ 5.0 bug or something..... When I used your solution, it worked perfectly, but only while I had the application running... When I closed, the whole computer crashed.

I have commented the second "if" block out and the program worked, that is, it didn't crash on close. It seems that the pMalloc->free isn't deallocating the memory correctly.

Do you know where are patches for borland c++ 5.0? or are there other ways to do it, without using the shell?

Thanks
Jaime
0
 
LVL 86

Expert Comment

by:jkr
ID: 1200933
Hmm, that's quite strange - I use the above code often (with VC++), but as it is 'plain' Win32, it should give no problems( i.e., Borland can hardly be blamed, as it is pure Windows API)... doing this without using the shell is like re-inventing the wheel.
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.

 

Author Comment

by:demarcy
ID: 1200934
Yes, I agree with you, it's quite easy that way, but is there a way to have total control over the dialog box created? for example, title, buttons, etc? I am using this function finally:

void TDirectoriesDlg::evSelRegDir( )
{
  char DirSelected[MAX_PATH];

  memset( DirSelected, 0, MAX_PATH );
  Logs->GetText( DirSelected, MAX_PATH );
  ChooseDirectory( DirSelected, "Registro" );
  Logs->SetText( DirSelected );
}

void TDirectoriesDlg::ChooseDirectory( char* Directorio, char* Que )
{
  BROWSEINFO BrowsingInfo;
  char DirPath[MAX_PATH];
  char FolderName[MAX_PATH];
  char Msg[40];
  LPITEMIDLIST ItemID;

  memset( &BrowsingInfo, 0, sizeof( BROWSEINFO ) );
  memset( DirPath, 0, MAX_PATH );
  BrowsingInfo.hwndOwner      = GetHandle( );
  BrowsingInfo.pszDisplayName = FolderName;
  wsprintf( Msg, "Elija el Directorio de %s", Que );
  BrowsingInfo.lpszTitle      = Msg;
  if( (ItemID = SHBrowseForFolder( &BrowsingInfo )) != NULL ) {
    SHGetPathFromIDList( ItemID, DirPath );
    GlobalFreePtr( ItemID );
    lstrcpy( Directorio, DirPath );
  }
}

This function looks really cute, but it would be better if the application (and computer) don't crash when I close it. As I told you, the dialog box works perfectly, I can choose a directory and everything and the application continue working perfectly too, doing all it has to do without crashing. The problem is when I exit the application. I have never had this sort of problem in my life :(

I was reasearching in the Windows 95 API help and I found some classes which are supposed to do it, they are TShellItem, TShellItemIterator, TPidl, TShellMalloc, etc. Looking at the source codes of them, they do all I was doing at first, so I'd prefer to use them so the shell operations will be well encapsulated, but I don't know how to use that classes because I don't have either examples or books about them. Do you know something about it? in VC++ maybe they exist too, but with names CShellItem, and so on.

An finally may I ask you for a great great favor? To make a last test and to discard a compiler problem, can you make that function a DLL? so I call it from my program to see what happen.

Thanks a lot

0
 
LVL 86

Expert Comment

by:jkr
ID: 1200935
You mean I should compile it into a DLL and send it to you - no problem, just give me some time ;-)

BTW: Are you able to find the crash address in a log file or debugger (DrWatson e.g.)?
0
 

Author Comment

by:demarcy
ID: 1200936
Yes, I have debugged it and I am able to know exactly in what address is the problem... the fact is that there's a MOV instruction whose source address is already undefined.

I have thought of a solution easier for you. Can you only compile it into an OBJ so I could link it in my project? that is easier than making it a DLL. I don't think the linker is the problem, so it is a good test I can do.

My e-mail is: jstuardo@SoftHome.net

Thanks
0
 
LVL 86

Expert Comment

by:jkr
ID: 1200937
>>Can you only compile it into an OBJ

Well, I could do that, but note that the MS .obj format is incompatible with BC++, so a DLL will definitly be better...
0
 

Author Comment

by:demarcy
ID: 1200938
Really???? ufff... what a bad thing, so let's try with a DLL :)

Thanks
0
 

Author Comment

by:demarcy
ID: 1200939
Ah! and I forgot, what VC++ version are you using?

please, when you program the DLL, can you do something like:

void ChooseDirectory( TDialog* Objeto, char* Directorio, char* Que )
{
  LPMALLOC pMalloc;
  BROWSEINFO BrowsingInfo;
  char FolderName[MAX_PATH];
  char Msg[40];
  LPITEMIDLIST ItemID;

  if  ( SHGetMalloc( &pMalloc ) == S_OK ) {
  // Get help on BROWSEINFO struct - it's got all the bit settings.
    BrowsingInfo.hwndOwner      = Objeto->GetHandle( );
    BrowsingInfo.pidlRoot       = NULL;
    BrowsingInfo.pszDisplayName = FolderName;
    wsprintf( Msg, "Elija el Directorio de %s", Que );
    BrowsingInfo.lpszTitle      = Msg;
    BrowsingInfo.ulFlags        = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
    BrowsingInfo.lpfn           = NULL;
    BrowsingInfo.lParam         = 0;

    // This next call issues the dialog box.
    if( (ItemID = SHBrowseForFolder ( &BrowsingInfo )) != NULL ) {
      if( SHGetPathFromIDList( ItemID, FolderName ) ) {
        // At this point pszBuffer contains the selected path */.
        lstrcpy( Directorio, FolderName );
        // Free the PIDL allocated by SHBrowseForFolder.
        pMalloc->Free( ItemID );
      }
    }
    // Release the shell's allocator.
    pMalloc->Release();
  }
}

That is to give a little customization to my application. I think instead of TDialog* you have to use CDialog*.

Thanks
0
 
LVL 86

Expert Comment

by:jkr
ID: 1200940
Will chage it to read

void ChooseDirectory( HWND hWnd, char* Directorio, char* Que )

so there will be no other libraries involved...

(expect to get it in 1h, but have to finish my DNS setup first - bet, I prefer real programming ;-)

0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

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

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

671 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