Contents
Monitoring Your PC's Memory Usage For Game Development
 
 
Printer-Friendly VersionPrinter-Friendly Version
 
Latest News
spacer View All spacer
 
November 21, 2009
 
Video Game Watchdog National Institute On Media And The Family Shutting Down [10]
 
Modern Warfare 2 Infinity Ward's 'Most Successful PC Version' Yet [12]
 
New Tech, Design Details Of Project Natal To Emerge At Gamefest In February
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
November 21, 2009
 
Sucker Punch Productions
Character Artist
 
Sucker Punch Productions
3D Environment Artist
 
Sucker Punch Productions
Network Programmer
 
Sucker Punch Productions
Texture Artist
 
Sony Online Entertainment
Brand Manager
 
Monolith Productions
Sr. Software Engineer, Engine - Monolith Productions - #113767
 
Crystal Dynamics
Sr. Level Designer
 
Gargantuan Studios
Lead World Designer
spacer
Latest Features
spacer View All spacer
 
November 21, 2009
 
arrow Upping The Craft: Susan O'Connor On Games Writing [6]
 
arrow Small Developers: Minimizing Risks in Large Productions - Part II [6]
 
arrow iPhone Piracy: The Inside Story [48]
 
arrow And Yet It Grows: Analyzing the Size and Growth of the European Game Market [5]
 
arrow NPD: Behind the Numbers, October 2009 [13]
 
arrow Reflecting On Uncharted 2: How They Did It [5]
 
arrow Sponsored Feature: Rasterization on Larrabee -- Adaptive Rasterization Helps Boost Efficiency
 
arrow Postmortem: Wadjet Eye's The Blackwell Convergence [2]
spacer
Latest Blogs
spacer View All     Post     RSS spacer
 
November 21, 2009
 
Accepting the Inherent Value of Games
 
Planckogenesis, Part II: Song Structure & Gravy Train [1]
 
Designing Games Is About Matching Personalities [1]
spacer
About
spacer News Director:
Leigh Alexander
Features Director:
Christian Nutt
Editor At Large:
Chris Remo
Advertising:
John 'Malik' Watson
Recruitment/Education:
Gina Gross
 
Features
  Monitoring Your PC's Memory Usage For Game Development
by Jelle van der Beek
0 comments
Share RSS
 
 
May 31, 2007 Article Start Previous Page 9 of 10 Next
 

Moving to C#

The samples we have seen so far have all been written in C++. The tool is written in C#, so here are a few pointers to get up and running with the sample code in C#.

First, it is important to note that the .NET framework has powerful support for processes. The Process class contains supports for both local and remote processes but I doubt whether handles to remote processes can be used in conjunction with the handles that have to be passed onto DbgHelp. This may be something to look into.

Advertisement

The code from listing 4, the EnumerateModules program, can be written in just a few lines of code in C#, as listing 6 demonstrates.

The remainders of the listings can be ported to C# relatively easy. There is just one tricky part, and that is calling functions to the various DLLs like DbgHelp.dll from C#. The .NET framework uses a system called platform invokes, often called p/invokes. A thorough discussion of this subject is beyond the scope of this document but the next listing will give you a head start. You need to import the functions into your C# code. Listing 7 demonstrates how to do this for most of the functions that we have used throughout the samples. Put these in your C# code and you will have little problems porting the C++ code to C#.

Process[] localProcesses = Process.GetProcesses();
foreach (Process process in localProcesses)
{
m_ProcessesListBox.Items.Add(new ProcessItem(process));
}

Listing 6: Enumerating the processes in C#.

 



public class DbgHelp
{
[Flags] public enum SymOpt : uint
{
CASE_INSENSITIVE = 0x00000001,
UNDNAME = 0x00000002,
DEFERRED_LOADS = 0x00000004,
NO_CPP = 0x00000008,
LOAD_LINES = 0x00000010,
OMAP_FIND_NEAREST = 0x00000020,
LOAD_ANYTHING = 0x00000040,
IGNORE_CVREC = 0x00000080,
NO_UNQUALIFIED_LOADS = 0x00000100,
FAIL_CRITICAL_ERRORS = 0x00000200,
EXACT_SYMBOLS = 0x00000400,
ALLOW_ABSOLUTE_SYMBOLS = 0x00000800,
IGNORE_NT_SYMPATH = 0x00001000,
INCLUDE_32BIT_MODULES = 0x00002000,
PUBLICS_ONLY = 0x00004000,
NO_PUBLICS = 0x00008000,
AUTO_PUBLICS = 0x00010000,
NO_IMAGE_SEARCH = 0x00020000,
SECURE = 0x00040000,
SYMOPT_DEBUG = 0x80000000
};

[Flags] public enum SymFlag : uint
{
VALUEPRESENT = 0x00000001,
REGISTER = 0x00000008,
REGREL = 0x00000010,
FRAMEREL = 0x00000020,
PARAMETER = 0x00000040,
LOCAL = 0x00000080,
CONSTANT = 0x00000100,
EXPORT = 0x00000200,
FORWARDER = 0x00000400,
FUNCTION = 0x00000800,
VIRTUAL = 0x00001000,
THUNK = 0x00002000,
TLSREL = 0x00004000,
}

[Flags] public enum SymTagEnum : uint
{
Null,
Exe,
Compiland,
CompilandDetails,
CompilandEnv,
Function,
Block,
Data,
Annotation,
Label,
PublicSymbol,
UDT,
Enum,
FunctionType,
PointerType,
ArrayType,
BaseType,
Typedef,
BaseClass,
Friend,
FunctionArgType,
FuncDebugStart,
FuncDebugEnd,
UsingNamespace,
VTableShape,
VTable,
Custom,
Thunk,
CustomType,
ManagedType,
Dimension
};

[StructLayout(LayoutKind.Sequential)]
public struct SYMBOL_INFO
{
public uint SizeOfStruct;
public uint TypeIndex;
public ulong Reserved1;
public ulong Reserved2;
public uint Reserved3;
public uint Size;
public ulong ModBase;
public SymFlag Flags;
public ulong Value;
public ulong Address;
public uint Register;
public uint Scope;
public SymTagEnum Tag;
public int NameLen;
public int MaxNameLen;

[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=1024)]
public string Name;
};

[StructLayout(LayoutKind.Sequential)]
public struct _IMAGEHLP_LINE64
{
public uint SizeOfStruct;
public uint Key;
public uint LineNumber;
public IntPtr FileName;
public ulong Address;
};

public delegate bool SymEnumSymbolsProc(ref SYMBOL_INFO pSymInfo, uint SymbolSize, IntPtr UserContext);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, bool fInvadeProcess);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern uint SymSetOptions(SymOpt SymOptions);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern ulong SymLoadModule64(IntPtr hProcess, IntPtr hFile,
string ImageName, string ModuleName,
ulong BaseOfDll, uint SizeOfDll);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern bool SymEnumSymbols(IntPtr hProcess, ulong BaseOfDll, string Mask, SymEnumSymbolsProc EnumSymbolsCallback, IntPtr UserContext);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern bool SymGetLineFromAddr64(IntPtr hProcess,
ulong dwAddr, ref uint pdwDisplacement, ref _IMAGEHLP_LINE64 Line);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern bool SymFromAddr(IntPtr hProcess,
ulong dwAddr, ref ulong pdwDisplacement, ref SYMBOL_INFO symbolInfo);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern bool SymEnumSymbolsForAddr(IntPtr hProcess,
ulong Address, SymEnumSymbolsProc EnumSymbolsCallback, IntPtr UserContext);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern bool SymUnloadModule64(IntPtr hProcess, ulong BaseOfDll);

[DllImport("dbghelp.dll", SetLastError=true)]
public static extern bool SymCleanup(IntPtr hProcess);
}

Listing 7: p/invoke signatures for some DbgHelp functions.

To read more about this subject, refer to8. One subpage from that reference that is particularly useful is the page about the type mappings from .NET to native Windows types9. If you know the type mappings it is generally not too difficult to come up with new signatures for p/invokes. As a last tip: www.pinvoke.net has a database of p/invoke signatures and there’s even a Visual Studio add-in that is connected to the database. Unfortunately the database does not contain any DbgHelp.dll functions at the time of writing.

 
Article Start Previous Page 9 of 10 Next
 
Comments

none
 
Comment:
 


Submit Comment