Jump to content

VisualAge C++ Tips: Difference between revisions

From EDM2
Ak120 (talk | contribs)
mNo edit summary
 
(7 intermediate revisions by 3 users not shown)
Line 1: Line 1:


==Use the Performance Analyzer==
==Use the Performance Analyzer==
;What Is It?
The Performance Analyzer is a marvellous tool for analysing the behaviour and performance of your applications. You create a trace file by running it along with your application, and then you analyse the data by looking at it with the Analyzer's 5 views:
*Call Nesting Diagram
*Dynamic Call Graph
*Execution Density Diagram
*Statistics Diagram
*Time Line Diagram
One of the most interesting is the Dynamic Call Graph:


====What Is It?====
The Performance Analyzer is a marvelous tool for analyzing the behavior and performance of your applications. You create a trace file by running it along with your application, and then you analyze the data by looking at it with the Analyzer's 5 views:
* Call Nesting Diagram
* Dynamic Call Graph
* Execution Density Diagram
* Statistics Diagram
* Time Line Diagram
One of the most interesting is the Dynamic Call Graph:
[Screen capture of Performance Analyzer Call Graph]
[Screen capture of Performance Analyzer Call Graph]


The nodes (rectangles) represent functions and the arcs (lines) represent calls.
The nodes (rectangles) represent functions and the arcs (lines) represent calls.


The size, shape, and color of the nodes gives information about the time spent in each function! Gray, blue, yellow, and red colors are used for functions which use up to 1/8, 1/4, 1/2, and the maximum of the total execution time, respectively. The height of a node depicts the execution time of a function, and the width depicts the active time (the time on the stack, even while a callee is running).
The size, shape, and colour of the nodes gives information about the time spent in each function! Gray, blue, yellow, and red colours are used for functions which use up to 1/8, 1/4, 1/2, and the maximum of the total execution time, respectively. The height of a node depicts the execution time of a function, and the width depicts the active time (the time on the stack, even while a callee is running).


The arcs are similarly colored to represent the frequency of calls.
The arcs are similarly coloured to represent the frequency of calls.


====How Is It Enabled?====
;How Is It Enabled?
If you're using the Workframe, enabling the Analyzer is as simple as clicking on the Build Smarts button on the toolbar, and selecting the Analyzer checkbox on the dialog that appears:


If you're using the workframe, enabling the Analyzer is as simple as clicking on the Build Smarts button on the toolbar, and selecting the Analyzer checkbox on the dialog that appears:
[[Image:VAC-smarts.jpg]]
[Build Smarts Dialog Box]


Then click on Build to rebuild your application with the the Analyzer enabled. To start the Analyzer, choose "Analize" from the Project menu.
'''Figure 2:''' Build Smarts Dialog Box
 
Then click on Build to rebuild your application with the Analyzer enabled. To start the Analyzer, choose "Analyze" from the Project menu.


==Use the Debug Memory Management Facilities==
==Use the Debug Memory Management Facilities==
;What are they?
====What are they?====
 
Debugging versions of malloc, calloc, realloc, free, new and delete
Debugging versions of malloc, calloc, realloc, free, new and delete


====What do they offer?====
;What do they offer?
 
:Information about memory you failed to free
    Information about memory you failed to free
:Notice that you are freeing already freed memory
    Notice that you are freeing already freed memory
:Notice that you wrote over freed memory
    Notice that you wrote over freed memory
 
====How do you enable them?====
 
Use the /Tm VisualAge C++ compiler option


====Sample Program====
;How do you enable them?:Use the /Tm VisualAge C++ compiler option


;Sample Program
Compile this program with /Tm. Run it with the w command line option (no slash) to write over memory which has already been freed. Notice that it catches the error. Run it again with the f command line option and watch it detect your freeing the same object twice.
Compile this program with /Tm. Run it with the w command line option (no slash) to write over memory which has already been freed. Notice that it catches the error. Run it again with the f command line option and watch it detect your freeing the same object twice.


Compile it again without /Tm and run it the same two ways. The memory management offenses are undetected.
Compile it again without /Tm and run it the same two ways. The memory management offenses are undetected.
<code>
  #include <stdlib.h>
#include <stdlib.h>
  #include <string.h>
#include <string.h>
 
  enum DemoMode
  enum DemoMode
  {
  {
Line 64: Line 51:
   FreeTwice = 'f'
   FreeTwice = 'f'
  };
  };
 
   
   
  void main (int argc, char ** argv)
  void main (int argc, char ** argv)
Line 90: Line 76:
   }
   }
  }
  }
</code>


==Use the IBM Open Class User Interface Library==
==Use the IBM Open Class User Interface Library==
Using the IBM Open Class User Interface Libraries (UICL, ICLUI) speeds application development. Let's compare some native PM code with the equivalent library code.
Using the IBM Open Class User Interface Libraries (UICL, ICLUI) speeds application development. Let's compare some native PM code with the equivalent library code.
{|class="wikitable"
 
{| class="wikitable" style="text-align:left" border="1"
|-
|-
|Dialog Box
!Dialog Box
|HAB hab = WinInitialize (0);
|HAB hab = WinInitialize (0);
HMQ hmq = WinCreateMsgQueue (hab, 0);
HMQ hmq = WinCreateMsgQueue (hab, 0);
Line 106: Line 91:
sampleDialog.showModally();
sampleDialog.showModally();
|-
|-
|Disable a Pushbutton
!Disable a Push button
|WinEnableWindow (WinWindowFromID (hwnd, DID_PRINT), FALSE);
|WinEnableWindow (WinWindowFromID (hwnd, DID_PRINT), FALSE);
|buttonPrint->disable();
|buttonPrint->disable();
|-
|-
|Access a Profile and Store Data in an MLE
!Access a Profile and Store Data in an MLE
|PrfQueryProfileData (HINI_USERPROFILE,(PSZ) "PMHPENV", (PSZ) "Address", pabBufAddr, &cbData);
|PrfQueryProfileData (HINI_USERPROFILE,(PSZ) "PMHPENV", (PSZ) "Address", pabBufAddr, &cbData);
WinSetDlgItemText (hwnd, DID_ADDR, pabBufAddr);
WinSetDlgItemText (hwnd, DID_ADDR, pabBufAddr);
|mleAddress->setText
|mleAddress->setText (profileEnv->elementWithKey (pszKeyAddr, pszKeyApp));
  (profileEnv->elementWithKey (pszKeyAddr,
  pszKeyApp));
|}
|}


==Use the Open Class User Interface Exceptions==
==Use the Open Class User Interface Exceptions==
This tip demonstrates 4 handy Open Class macros which help you throw exceptions to report errors.
This tip demonstrates 4 handy Open Class macros which help you throw exceptions to report errors.


====Sample Program====
;Sample Program
 
======Running the Program======
 
For best results, run it with the run.cmd contained in the zip file (throwdem.zip, 5,279 bytes), and make sure you have pmprintf.exe in the path. You can run it without pmprintf, but if you do, then do not use run.cmd. Instead, type the following commands:
 
set ICLUI TRACETO=STDERRthrowdem 2>err


;Running the Program
For best results, run it with the run.cmd contained in the zip file ([https://web.archive.org/web/19970122170208if_/http://www.davebsoft.com:80/Programming/tips/UICLExceptions/throwdem.zip throwdem.zip], 5,279 bytes), and make sure you have pmprintf.exe in the path. You can run it without pmprintf, but if you do, then do not use run.cmd. Instead, type the following commands:
set ICLUI TRACETO=STDERR
throwdem 2>err
When the program starts, choose one of the menu options, and then exit the program and look into the err file.
When the program starts, choose one of the menu options, and then exit the program and look into the err file.


======Source Code Listing======
;Source Code Listing
 
This program is designed to be self-explanatory.
Browser FixedThis program is designed to be self-explanatory.
<code>
 
  /*
  /*
     UICL Throw Error Macros Demo - Dave Briccetti (daveb@davebsoft.com), Jan. 1995.
     UICL Throw Error Macros Demo - Dave Briccetti (daveb@davebsoft.com), Jan. 1995.
Line 145: Line 124:
         IASSERTSTATE        Ensure an object's state is valid for a function call
         IASSERTSTATE        Ensure an object's state is valid for a function call
         ITHROWGUIERROR      Use when PM function fails
         ITHROWGUIERROR      Use when PM function fails
         ITHROWSYSTEMERROR  Use when a system function fails  
         ITHROWSYSTEMERROR  Use when a system function fails
  */
  */
   
   
Line 205: Line 184:
         }
         }
     }
     }
     catch (const IException & except) {}  
     catch (const IException & except) {}
     return true;
     return true;
  }
  }
</code>


[[Category:Tools Articles]]
[[Category:UICL]]

Latest revision as of 19:37, 16 December 2022

Use the Performance Analyzer

What Is It?

The Performance Analyzer is a marvellous tool for analysing the behaviour and performance of your applications. You create a trace file by running it along with your application, and then you analyse the data by looking at it with the Analyzer's 5 views:

  • Call Nesting Diagram
  • Dynamic Call Graph
  • Execution Density Diagram
  • Statistics Diagram
  • Time Line Diagram

One of the most interesting is the Dynamic Call Graph:

[Screen capture of Performance Analyzer Call Graph]

The nodes (rectangles) represent functions and the arcs (lines) represent calls.

The size, shape, and colour of the nodes gives information about the time spent in each function! Gray, blue, yellow, and red colours are used for functions which use up to 1/8, 1/4, 1/2, and the maximum of the total execution time, respectively. The height of a node depicts the execution time of a function, and the width depicts the active time (the time on the stack, even while a callee is running).

The arcs are similarly coloured to represent the frequency of calls.

How Is It Enabled?

If you're using the Workframe, enabling the Analyzer is as simple as clicking on the Build Smarts button on the toolbar, and selecting the Analyzer checkbox on the dialog that appears:

Figure 2: Build Smarts Dialog Box

Then click on Build to rebuild your application with the Analyzer enabled. To start the Analyzer, choose "Analyze" from the Project menu.

Use the Debug Memory Management Facilities

What are they?

Debugging versions of malloc, calloc, realloc, free, new and delete

What do they offer?
Information about memory you failed to free
Notice that you are freeing already freed memory
Notice that you wrote over freed memory
How do you enable them?
Use the /Tm VisualAge C++ compiler option
Sample Program

Compile this program with /Tm. Run it with the w command line option (no slash) to write over memory which has already been freed. Notice that it catches the error. Run it again with the f command line option and watch it detect your freeing the same object twice.

Compile it again without /Tm and run it the same two ways. The memory management offenses are undetected.

#include <stdlib.h>
#include <string.h>

enum DemoMode
{
  WriteOverFreed = 'w',
  FreeTwice = 'f'
};

void main (int argc, char ** argv)
{
  if (argc == 2)
  {
    char * psz = new char [20];
    strcpy (psz, "String 1");
    _dump_allocated (10);


    switch (argv[1][0])
    {
      case WriteOverFreed:
        delete [] psz;
        strcpy (psz, "String 2");
        _heap_check ();
        break;

      case FreeTwice:
        delete [] psz;
        delete [] psz;
        break;
    }
  }
}

Use the IBM Open Class User Interface Library

Using the IBM Open Class User Interface Libraries (UICL, ICLUI) speeds application development. Let's compare some native PM code with the equivalent library code.

Dialog Box HAB hab = WinInitialize (0);

HMQ hmq = WinCreateMsgQueue (hab, 0); HWND hwndDlg = WinDlgBox (HWND_DESKTOP, HWND_DESKTOP, DlgProc, 0, DID_DLG, 0); WinDestroyMsgQueue (hmq); WinTerminate (hab);

SampleDialog sampleDialog;

sampleDialog.showModally();

Disable a Push button WinEnableWindow (WinWindowFromID (hwnd, DID_PRINT), FALSE); buttonPrint->disable();
Access a Profile and Store Data in an MLE PrfQueryProfileData (HINI_USERPROFILE,(PSZ) "PMHPENV", (PSZ) "Address", pabBufAddr, &cbData);

WinSetDlgItemText (hwnd, DID_ADDR, pabBufAddr);

mleAddress->setText (profileEnv->elementWithKey (pszKeyAddr, pszKeyApp));

Use the Open Class User Interface Exceptions

This tip demonstrates 4 handy Open Class macros which help you throw exceptions to report errors.

Sample Program
Running the Program

For best results, run it with the run.cmd contained in the zip file (throwdem.zip, 5,279 bytes), and make sure you have pmprintf.exe in the path. You can run it without pmprintf, but if you do, then do not use run.cmd. Instead, type the following commands:

set ICLUI TRACETO=STDERR
throwdem 2>err

When the program starts, choose one of the menu options, and then exit the program and look into the err file.

Source Code Listing

This program is designed to be self-explanatory.

/*
   UICL Throw Error Macros Demo - Dave Briccetti (daveb@davebsoft.com), Jan. 1995.
  
   This tip demonstrates the use of several handy error-reporting macros
   included in the C Set++ User Interface Class Library:

       IASSERTPARM         Check the validity of parameters passed to functions
       IASSERTSTATE        Ensure an object's state is valid for a function call
       ITHROWGUIERROR      Use when PM function fails
       ITHROWSYSTEMERROR   Use when a system function fails
*/

#define INCL_DOSMEMMGR
#define INCL_DOSERRORS
#define INCL_WINWINDOWMGR
#include <os2.h>
#include <icmdhdr.hpp>                      // Command handler
#include <iexcept.hpp>                      // Exceptions
#include <iframe.hpp>                       // Frame
#include "idres.h"

class AppCommandHandler : public ICommandHandler    // Command handler for menu
{
   virtual Boolean command (ICommandEvent & cmdEvent);
};

void main()                    
{
   IFrameWindow frame (IDFRAME_MAIN,       // Create frame window with menu
       IFrameWindow::defaultStyle() | IFrameWindow::menuBar);
   AppCommandHandler appCommandHandler;    // Create a command handler and
   appCommandHandler.handleEventsFor (&frame); // assign it to the frame
   frame.setFocus ();                      // Set focus to the frame window
   frame.show ();                          // Show the frame
   IApplication::current().run();          // Run the application
}

static void CheckParameter (int Parm)       // Function which checks parmeter
{
    IASSERTPARM (Parm > 0);                 // Throw exception if false
}

AppCommandHandler :: command (ICommandEvent & cmdEvent)
{
   static const BOOL           fSystemReady = FALSE;
   static const IWindowHandle  windowHandleBad     = 999;
   static const PVOID          pvBadAddress        = (PVOID) 999;
   try                                     // Catch all the errors we throw
   {
       switch (cmdEvent.commandId())
       {
           case IDM_ASSERTPARM:            // Pass bad parm to function
               CheckParameter (0);        
               break;
           case IDM_ASSERTSTATE:           // Check state before proceeding
               IASSERTSTATE (fSystemReady);
               break;
           case IDM_GUI:                   // Make a bad PM call
               if (! WinShowWindow (windowHandleBad, TRUE))
                   ITHROWGUIERROR ("WinShowWindow");
               break;
           case IDM_CP:                    // Make a bad system call
               const APIRET rc = DosFreeMem (pvBadAddress);
               if (rc != NO_ERROR)
                   ITHROWSYSTEMERROR (rc, "DosFreeMem",
                       IErrorInfo::accessError, IException::recoverable);
               break;
       }
   }
   catch (const IException & except) {}
   return true;
}