INFO: Troubleshooting CAP/WST Utilities Under Windows NT

This article was previously published under Q169275
This article has been archived. It is offered "as is" and will no longer be updated.
This article provides a collection of tips, tricks, and traps to you canuse to avoid and solve common problems that you may encounter while usingthe Call Attribute Profiler (CAP) and Working Set Tuner (WST) utilities forWindows NT and Windows 2000. Note that these utilities are included with the Win32 Software Development Kit. You can use these powerful utilities to make your application run faster and use less RAM.

This article assumes that you have read the preliminary information on theuse of these tools that is available in the Win32 SDK Tools documentation.The information in this article applies to the versions of CAP/WSTutilities that are shipped on the January 97 Win32 SDK or later.

Preparing Your Application

We recommend that you build applications that you want to tune with CAP orWST with slightly different switches than the documentation suggests. Forthe compiler, use /Zi or /Z7 (don't forget /Gh). For the linker, use /debug/debugtype:both and /pdb:<name>.pdb or /pdb:none.

One benefit of using these switches is that you can do full symbolicdebugging under the Visual C++ or WinDbg debugger in case either the CAP orWST utility manages to flush out a problem in your code. This is morecommon than you may think. For example, /Gh causes the compiler to insert acall to a function called _penter() in front of each and every function inyour code. This global increase in code size causes your functions to loadinto slightly different offsets in memory, which may cause a pointer bug orarray-overrun bug in your code to now show itself. By using these switches,you can debug your application normally when it is compiled for CAP/WST.

TIP: We recommend that you do not use capsetup.exe to prepare yourapplications for tuning. Instead, building your applications with theproper switches works more reliably.

TRAP: Running "capsetup -a" and then building your application for tuningcauses the CAP utility to not work. Just avoid Capsetup.exe if you can.

Tuning/Profiling DLLs and OCXs

Tuning DLLs and OCXs is fairly straightforward for both CAP and WST, onceyou know the details, though the procedure is slightly different for each.


When an executable compiled for WST is initialized, WST gets control andlooks at all the DLLs loaded in that process's memory space. Only DLLs thatare present and built for WST are tuned, which means that the DLLs must bestatically linked. Dynamically-loaded DLLs (and OCXs) are not tuned eventhough they may be compiled for tuning.

TRICK: However, you can tune all static DLLs/OCXs. The trick is to buildonly the DLL/OCXs that you want to tune for tuning. Do not build theexecutable for tuning. Then do the following:
  1. Remove the name of the .exe from the [exes] section in WST.ini file to cut down on extraneous output files in the output directory.
  2. Put the name of the DLL/OCX into the [exes] section in WST.ini.
  3. The symbols for the DLL/OCX (whether it is the DLL/OCX itself, or a .dbg or .pdb file) must be on the symbol search path (which is %_NT_SYMBOL_PATH%, %_NT_ALT_SYMBOL_PATH%, %SystemRoot%, and the working directory, in that order). Otherwise, you will get empty output files in the WST directory. This is especially important for an OCX, which is usually residing (and also usually registered) in another directory.
TIP: We have had best luck by simply putting and registering the DLL/OCX inthe same directory as the executable, or by making sure the applicationand DLL/OCX are in subdirectories of the current directory when you run theexecutable.

TRAP: You will get output files for static DLL/OCXs loaded after thedesired module anyway. If present, the environment variables%_NT_SYMBOL_PATH% and %_NT_ALT_SYMBOL_PATH% might each contain only onepath containing less than 256 characters.

For additional information, please see the following article in theMicrosoft Knowledge Base:
148659 How to Set Up Windows NT Debug Symbols


Fortunately, CAP supports dynamically loaded libraries without any specialcaveats. You just need to make sure that loadlibrary=on in the CAP.inifile. However, if you're not getting symbolic information for your DLLs,you can try something similar to the procedure for WST--except you must putthe name of the .exe in the [exes] section, unlike for WST.

Known Problems, Limitations

The following is a list of known problems and limitations with the CAP andWST utilities. It's best to contact Microsoft Professsional Support Services for helpwith any problems encountered with these utilities. A support professional maybe able to provide a workaround or help with critical problems.
  1. If you are tuning with CAP/WST under Windows NT version 3.51 and run into problems, it is highly recommended that you switch to Windows NT version 4.0 and use the latest version of CAP/WST utilities from the Platform SDK.

    TIP: Note that you can use CAP.DLL for Windows NT 4.0 on a Windows NT Version 3.51. However, you must copy IMAGEHLP.dll from Windows NT 4.0 into your application's directory that you are tuning because the latest version of CAP/WST utilities need an updated IMAGEHLP.DLL to do symbol lookups. Be careful not to replace the IMAGEHLP.DLL in the Window NT 3.51 %systemroot%\system32 directory.
  2. On rare occasions, when using CAP, a fault occurs in the C-runtime library's strcpy() function call from CAP.dll. This causes the target DLL, that is being tuned by CAP, to not load its symbols. This results in missing symbols in the .END file after a profile run for such a DLL. Unfortunately, this could be the DLL or OCX that you are trying to tune, as opposed to a child or system DLL. You can identify this problem if you have linked with the debug C-runtime (CRT) library and you see strcpy() at the top of the call stack in the debugger after stopping at the second-chance exception.

    We are researching this known problem with the CAP utility and will post new information here in the Microsoft Knowledge Base as it becomes available.
  3. The system IMAGEHLP.dll for Windows NT versions 4.0 with Service Pack 2 (and previous versions of Windows NT) returns corrupted symbolic name strings when CAP is doing symbol lookups and when the setting "undecorate=off" is set in CAP.ini. In this situation, your .END file will contain a few "garbage" characters embedded, usually a control-Z. In addition, this problem could also crash Capview.exe utility. This problem can typically be fixed by stripping out any non-printable characters from your .END file.

    We are researching this known problem with the CAP utility and will post new information here in the Microsoft Knowledge Base as it becomes available.
  4. The CAP tool has certain problems with Visual C++ style exception- handling. If a Visual C++ exception occurs, CAP does not correctly clean up the stack, causing strange crashes and application lockups. In order to avoid this problem, you have to modify your application so that no Visual C++ exceptions occur during a profile run. Note that this problem may also occur with the WST utility, since both these utilities share common code.

    We are researching this known problem with CAP, WST utilities and will post new information here in the Microsoft Knowledge Base as it becomes available.
  5. WST cannot tune static functions. This is due to a limitation of the Visual C++ linker. When WST encounters static functions, it will tune them like other functions and they will be listed in the .PRF output file. But, the Visual C++ linker cannot reorder static functions, and, consequently, will generate a few harmless warnings that it is unable to reorder them.

    Note that for Visual C++ applications you may see some mysterious static functions in the .prf file with a name in the format of _$Ennn, where "nnn" is some numeric value. These are static helper functions generated by the compiler. WST puts these function names in the .PRF output, but the resulting linker warnings can be safely ignored. Unfortunately these static functions (and any that you defined in your application) will not be reordered and, consequently, will not be tuned either.
  6. The section headers in the WST.ini and CAP.ini initialization files must appear in the same order as the example files copied during setup. A missing or misspelled section header causes WST to ignore the remaining portion of WST.ini. Although it must be present, WST completely ignores the [PATCH IMPORTS] section of the WST.ini initialization file.
  7. WST might fail to initialize when tuning extremely large projects. This might cause the application being tuned to freeze on startup. A warning message that the system is low on virtual memory might indicate that too many symbols exist in the modules to be tuned. In this case, reducing the number of modules built for tuning or adding more RAM to the test computer may help.
  8. WSTune.exe cannot dump analysis data for modules whose base file name is greater than 17 characters.

CAP Memory Usage Information

CAP memory usage can be a factor in the performance of your application. IfCAP's memory usage becomes too great (usually due to a lot of chronologicaldata), this will result in a lot of swapping, which in turn can affect theperformance of your application.

CAP's memory usage can be divided into the following three groups (orderedfrom smallest to largest):
  1. Symbol information.
  2. Calling tree structure.
  3. Chronological calling data.
The symbol data is loaded when the app starts, and also when a DLL isdynamically loaded (if 'loadlibrary=on' in CAP.ini). The symbol informationis a kind of dictionary, mapping function names to raw hex addresses. Thisallows CAP to log the profile information by name rather than hexaddresses. The size of the symbol information depends on how many DLL's areloaded, and how many symbols are in each DLL.

The calling tree structure is continuously built as the profiledapplication executes. Each node in this tree represents one caller-calleepair. For example, the first time function A calls function B, a new nodeis created. Each additional call from function A to function B changes theprofiling values in node A-B, but does not increase the storage space. Sothe size of the calling tree is dependent on the number of caller-calleerelations that are actually exercised by the application. Each noderequires 80 bytes of memory.

The calling tree information is dumped to the log file and provides theinput for Capview.exe. It contains information such as the number of timesfunction A called function B, the shortest/longest/average time function Bexecuted when called by function A, and how much of function B's time wasdue to calls that it made itself.

Chronological calling data is by far the largest user of CAP memory. Unlikethe calling tree data, the chronological data contains a data cell forevery function call that occurs. If function A calls function B 100 times,100 cells are created. This allows for a very detailed log that shows theexact order that calls were made and how much time each call took. The sizeof the chronological data, then, depends on how many function calls aremade by the application. Each data cell requires 40 bytes.

Preparing to Contact Professional Support Services

When CAP or WST fails, the most common symptoms are failure to produce anyoutput or an exception while your application executes (usually duringinitialization). To determine if the failure is due to a problem in CAP.dllor WST.dll, you will have to debug your application. When you hit a 2nd-chance exception in the debugger (ignore all 1st-chance exceptions - theyare normal and are handled by an exception handler in CAP/WST), look at thetop of the call stack to see if the exception occurred in CAP or WST. To dothis, use LINK -dump -headers on CAP.dll or WST.dll (or you can do a "quickview" in Windows Explorer on the DLL) and note the image base address andthe "size of image" value. If the address where the exception occurred iswithin image base + size of image, then you have most likely encountered abug in CAP.dll or WST.dll.

Before contacting Microsoft Professional Support Services for help in diagnosing theproblem, please debug your application and do the following (theseinstructions are for an x86 machine). Visual C instructions are for version5.0 and later:

  1. Dump the stack as follows:

    WinDbg: In the command window, enter "dd esp" and leave the output there.

    Visual C debugger: On the View menu, click Debug Windows, click Memory, enter "esp", and then copy downward 20 lines or so (right-click, then click Copy). Paste it into a new document in Notepad or any other editor.
  2. Get the contents of the registers as follows:

    WinDbg: In the command window, type r.

    Visual C debugger: Get the contents of the registers from the View menu, Debug Windows menu, Registers window.
  3. Get the call stack as follows:

    WinDbg: In the command window, type kbsv. Visual C debugger: On the View menu, Debug Windows menu, Call Stack. Copy everything.
  4. Get a disassembly listing of the code around the exception as follows: WinDbg: Click the assembly toolbar button (with the 1's and 0's in it) and get a screenful of code both above and below the address of the 2nd- chance exception.

    Visual C debugger: On the View menu, Debug Windows menu, click Disassembly. Copy a few pages above and below the address of the exception.
  5. Assemble information as follows:

    WinDbg: The output from all the commands that you typed into the command window should still be in the command window. Scroll back in the command window, copy all the debug output from CAP/WST, and include the stack dump, register dump, and call stack you created.

    Visual C debugger: Copy the output from CAP/WST from the Debug window into your document.
TIP: To skip past all the 1st-chance exceptions that you may hit whendebugging CAP-compiled applications (which are normal) do the following:

WinDbg: On the Options menu, click Exceptions, set "Access Violation"(0xc0000005) to "Notify", and then click Change.

Visual C debugger: On the Debug menu, click Exceptions and make sure that"access violation" is set to "stop if not handled".
Win32 SDK Tools documentation
debug tls base

Article ID: 169275 - Last Review: 01/09/2015 07:01:23 - Revision: 1.1

  • Microsoft Platform Software Development Kit-January 2000 Edition
  • kbnosurvey kbarchive kbinfo KB169275