Page 1 of 1

Field values using API

Posted: Thu Jun 23, 2016 3:09 pm
by momono
Hi,

I'm trying to get values for objects from API. My intend is to rebuild the object from data that are availble in dump.
I've retrieved TypeInstance using comparison.GetTypeInstance(instanceId) but it returns only reference fields on GetReferencesAndFields(ReferencesOption.Default) call. I require to get all fields and their values (even for value types). But I can't find any method to retrieve value types fields and their values.
I'm using version 5.0.142

Thanks for help.

Edit:
For me it would be also sufficient to get all instances of type in FE and export them to file like string values. I need to confirm that some instance of type with certain value was in memory.

Re: Field values using API

Posted: Fri Jun 24, 2016 1:43 pm
by momono
I was able to identify correct instance by traversing all instance of type and checking for id. Id is type of YourType. You have to know its size and position so it make some time to find.In my case its struct holding long.
First four bytes in GetInstanceData seems to contain instanceId or whatever which is not related to actual data.

Code: Select all

TypeInstance instance = comparison.GetTypeInstance(instanceId);
var arrBytes = instance.GetInstanceData();
var eightBytesPtr = Marshal.AllocHGlobal(8);
Marshal.Copy(arrBytes, 4, eightBytesPtr, 8);
YourType id = (YourType)Marshal.PtrToStructure(eightBytesPtr, typeof(YourType));
Marshal.FreeHGlobal(eightBytesPtr);
So this showed me right instance and now I can work in profiler normally by filtering instance id.

Re: Field values using API

Posted: Mon Jun 27, 2016 4:21 pm
by Andreas Suurkuusk
There is a helper class named SciTech.Profiler.InstanceDataRetriever that can be used to parse the instance data of an instance in a profiler snapshot. The example code below shows how field information can be retrieved.

Code: Select all

var retriever = new InstanceDataRetriever(comparison);

int maxFields = 1000;
RetrievedFieldDataCollection fields = retriever.RetrieveFields(instanceId, maxFields);

if( fields.HasMissingFields )
{
    // Fields may be missing under some circumstances, e.g. uninitialized nested value types.
    Console.WriteLine("One or more fields are missing in the collection.");
}

if( fields.IsTruncated)
{
    // Arrays and strings may be truncated if the number of items exceeds maxFields
    Console.WriteLine("Fields collection is truncated.");
}

foreach( var field in fields )
{
    Console.WriteLine($"{field.Field.Name}: {field.Value}");
    if( field.Value is TypeInstanceId )
    {
        Console.WriteLine("  Field is a reference field.");
    }

    if( field.SubFields.Count > 0 )
    {
        Console.WriteLine("  Instance has nested value type fields.");
    }
}
Using PtrToStructure to retrieve instance data is not safe, since the instance data layout is often different from the .NET marshalling layout. However, the fields information retrieved by InstanceDataRetriever is more suitable for presentation than programmatic analysis. I will try to write an sample that uses the InstanceDataRetriever to unmarshal the instance data to an actual instance of the type, similar to the PtrToStructure method.