Null pointer dereference while calling gvLayout (gvc->textfont_dt in labels.c, line 35)
Exception thrown at 0x1002AF71 (gvc.dll) in ProjectDependencyVisualizer.Desktop.exe: 0xC0000005: Access violation reading location 0x00000000.
I'm happy to provide a .zip containing a complete repro if it would be useful. The project is C# with the platform target set to x86. The following DLLs are copied to bin output, originally from the release/lib/release/dll
and release/bin
folders in https://graphviz.gitlab.io/_pages/Download/windows/graphviz-2.38.zip:
cdt.dll
cgraph.dll
gvc.dll
gvplugin_dot_layout.dll
gvplugin_gdiplus.dll
libexpat.dll
ltdl.dll
Pathplan.dll
zlib1.dll
These are my p/invoke declarations:
internal static class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern SafeModuleHandle LoadLibrary(string lpLibFileName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, BestFitMapping = false, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr GetProcAddress(SafeModuleHandle hModule, string lpProcName);
[DllImport("gvc.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern SafeGraphvizContextHandle gvContext();
[DllImport("gvc.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gvAddLibrary(SafeGraphvizContextHandle gvc, IntPtr lib);
[DllImport("cgraph.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern SafeGraphHandle agmemread(string cp);
[DllImport("gvc.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "gvLayout", CharSet = CharSet.Ansi)]
private static extern int gvLayoutExtern(SafeGraphvizContextHandle gvc, SafeGraphHandle g, string engine);
public static SafeLayoutHandle gvLayout(SafeGraphvizContextHandle gvc, SafeGraphHandle g, string engine)
{
if (gvLayoutExtern(gvc, g, engine) != 0)
{
return new SafeLayoutHandle(contextHandle: null, graphHandle: null);
}
return new SafeLayoutHandle(gvc, g);
}
[DllImport("gvc.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int gvRenderContext(SafeGraphvizContextHandle gvc, SafeGraphHandle g, string format, HandleRef context);
}
Here I've stripped away the C# object model to simplify the repro and recreated the call pattern against the bare p/invoke declarations:
using (var context = NativeMethods.gvContext())
using (var dotLayoutLib = NativeMethods.LoadLibrary("gvplugin_dot_layout.dll"))
{
NativeMethods.gvAddLibrary(context,
NativeMethods.GetProcAddress(dotLayoutLib, "gvplugin_dot_layout_LTX_library"));
using (var graph = NativeMethods.agmemread("graph { a -- b }"))
{
if (graph.IsInvalid) throw new Exception("Failed to create a graph for the specified source.");
// gvLayout throws AccessViolationException
using (var layout = NativeMethods.gvLayout(context, graph, "dot"))
{
}
}
}