Profiling Routines That Have Unsafe Code

Applies to AQTime 8.81, last modified on January 18, 2022

Some of AQTime’s profilers cannot profile routines that include unsafe code. Unsafe code means that your routine’s binary code contains both binary code instructions and data (numeric and string constants, jump tables and so on). AQTime cannot isolate these two from each other. This may happen with some Delphi and Visual C++ routines that contain strings or ASSERTs. Another possible cause of unsafe code is exception handling. The compiler places the data after the ret instruction, but debug information “includes” the data size into the routine’s code, so AQTime cannot determine where the routine’s binary code ends in memory. Below are examples of two routines that are possible candidates for having unsafe code:

Visual C++

void MyFunc()
{
  ...
  int cnt = objCollection->getCount();
  ASSERT(cnt < 0, "Invalid value.");
  ...
}

Delphi

procedure MyFunc()
begin
  ...
  MessageBox(0, 'Text', 'Caption', MB_OK);
  ...
end;

To solve the problem, do the following:

  • If the problem occurs when profiling routines at the line level, try to profile them at the routine level, and vice versa. See About Profiling Levels.

  • If you use the Borland C++ Builder compiler, disable optimization in the compiler settings.

  • Change the source code in order for the compiler to generate binary code in a different way. Here are some possible ways to do this:

    • If you use the Debug configuration for your Visual C++ application, recompile it in the Release configuration.

    • Divide your routine into a number of routines with smaller sizes. This will decrease the amount of data kept within the routine’s binary code.

    • Try to decrease the amount of data kept within the routine’s code by moving string constants outside the routine. For instance, if your routine includes a call to the MessageBox function:

      Delphi

      procedure MyFunc()
      begin
        ...
        MessageBox(0, 'Text', 'Caption', MB_OK);
        ...
      end;

      You can declare two string variables, which contain the ‘Text’ and ‘Caption’ string values, outside the routine and use them in the MessageBox function:

      Delphi

      string cText = 'Text';
      string cCaption = 'Caption';
       
      procedure MyFunc()
      begin
        ...
        MessageBox(0, cText, cCaption, MB_OK);
        ...
      end;

      You can also try to declare string constants containing string values inside the routine. In this case, the visibility scope of the constants is limited by the current routine, not by the unit.

      Delphi

      procedure MyFunc()
      const
        cText='Text';
        cCaption='Caption';
      begin
        ...
        MessageBox(0, cText, cCaption, MB_OK);
        ...
      end;

    • Create a stub routine that will call your routine and profile this stub routine at line level:

      Visual C++

      #pragma optimize("", off)
      void StubFunc(int someValue)
      {
        MyFunc(someValue);
      }
      #pragma optimize("", on)

      We used the #pragma optimize directives to make sure that StubFunc occupies more than five bytes in memory. This is a rare case, however. If a routine uses at least one parameter, or if it calls another function, its binary code will be larger than five bytes.

    • If you know what code line causes the unsafe code message, move it to a separate routine. For example, if you find out that AQTime marks your exception handling routine as unsafe, you can separate the exception handling code from the rest of your code in the following way:

      Delphi

      procedure MyLogic;
      begin
        // do something
      end;

      procedure MyUnsafeProcedure;
      begin
        try
          MyLogic;
        except
          on E : Exception do // you know that this line causes unsafe code
          begin
            // do something
          end;
        end;
      end;

      Now, AQTime will not profile only the exception handling routine.

See Also

Profiling Various Applications and Code
Routines That Cannot Be Profiled
Performance Profiler - Report Panel
Coverage Profiler - Report Panel

Highlight search results