[Mono-list] Memory Allocation in unmanaged code

Jim Fehlig jfehlig@novell.com
Wed, 08 Sep 2004 15:43:48 -0600


This is a MIME message. If you are reading this text, you may want to 
consider changing to a mail reader or gateway that understands how to 
properly handle MIME multipart messages.

--=__Part6F4F1C04.0__=
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit

>>>Jonathan Pryor <jonpryor@vt.edu> 09/06/04 4:57 pm >>> 
 
>Correctness depends upon the ListLocalPrinters() documentation.  What
is 
>`printerList' supposed to be?  Just a pointer to a 
>CupsPrinterListStruct*?  Or should it be an array of pointers?  How
many 
>elements will be addressed? 
 
Thanks for your insights and observations - very informative.  As you 
deduced, printerList is a pointer to a CupsPrinterListStruct*.  I 
modified the wrapper implementation to use unsafe code but still 
unsuccessful in retrieving properties from the C# structure below. 
The unmanaged ListLocalPrinters is returning a list containing 1 
element yet the loop in PrintLibWrapper.ListLocalPrinters is executed 
twice, throwing a NullReferenceException when printer =
printer->nextElement 
is executed on the second pass.  Further, a NullReferenceException is 
thrown on the first iteration through the loop by simply invoking 
Console.WriteLine(PrinterInfo: {0}, {1}, pl.Name, pl.Uri). 
I have tried several attributes on the structure elements with no change

in behavior.  I believe the problem is in the marshalling attributes,
but 
I have yet to discover how to examine the memory in mono on linux. 
Installing/configuring a windows client and running/debugging there 
may be the easiest path. 
 
Thanks again for the help. 
Jim 
 
// interop struct 
[ StructLayout(LayoutKind.Sequential) ] 
private*unsafe*struct*InternalPrinterList 
{ 
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)] 
   public string printerUri; 
 
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)] 
   public string printerCupsUri; 
 
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)] 
   public string printerName; 
 
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/,SizeConst=81)] 
   public*string*printerMakeModel; 
 
   [MarshalAs(UnmanagedType.U4)] 
   public InternalPrinterList *nextElement; 
} 
 
// Convert linked list constructed by unmanaged code to 
// array of user-visible PrinterList objects. 
public static unsafe PrinterList[] ListLocalPrinters() 
{ 
   IntPtr list = IntPtr.Zero; 
   try 
   { 
      ListLocalPrinters(ref list); 
      InternalPrinterList* printer = (InternalPrinterList *)list; 
      ArrayList printers = new ArrayList(); 
      while (printer != null) 
      { 
         PrinterList pl = new PrinterList(); 
         pl.Uri = printer->printerUri; 
         pl.CupsUri = printer->printerCupsUri; 
         pl.Name = printer->printerName; 
         pl.MakeModel = printer->printerMakeModel; 
         // throws NullReferenceException 
         Console.WriteLine(PrinterInfo: {0}, {1}, pl.Name, pl.Uri); 
 
         printers.Add(pl); 
         // Something not right here as we will go through again 
         // even when list contains only 1 element. 
         printer = printer->nextElement; 
       } 
       PrinterList[] rval = new PrinterList[printers.Count]; 
       printers.CopyTo(rval); 
       return rval; 
   } 
   catch (Exception e) 
   { 
       return new PrinterList[0]; 
   } 
   finally 
   { 
      if (list != IntPtr.Zero) 
         FreeLocalPrinterList(list); 
   } 
} 


--=__Part6F4F1C04.0__=
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
   =20
  </head>
  <body style=3D"margin-bottom: 1px; margin-right: 4px; margin-left: 4px; =
margin-top: 4px">
  <DIV>    &gt;&gt;&gt;Jonathan Pryor &lt;jonpryor@vt.edu&gt; 09/06/04 =
4:57 pm &gt;&gt;&gt;

    <DIV>&nbsp;</DIV>
    <DIV>    &gt;Correctness depends upon the ListLocalPrinters() =
documentation.&#160;&nbsp;What is
    <DIV>&gt;`printerList' supposed to be?&#160;&nbsp;Just a pointer to a
    <DIV>&gt;CupsPrinterListStruct*?&#160;&nbsp;Or should it be an array =
of pointers?&#160;&nbsp;How many
    <DIV>&gt;elements will be addressed?

    <DIV>&nbsp;</DIV>
    <DIV>
      Thanks for your insights and observations - very informative. =
&nbsp;As you
    </DIV>
    <DIV>
      deduced, &quot;printerList&quot; is a pointer to a CupsPrinterListStr=
uct*. &nbsp;I
    </DIV>
    <DIV>
      modified the wrapper implementation to use &quot;unsafe&quot; code =
but still
    </DIV>
    <DIV>
      unsuccessful in retrieving properties from the C# structure below.
    </DIV>
    <DIV>
      The unmanaged ListLocalPrinters is returning a list containing 1
    </DIV>
    <DIV>
      element yet the loop in PrintLibWrapper.ListLocalPrinters is =
executed
    </DIV>
    <DIV>
      twice, throwing a NullReferenceException when &quot;printer =3D =
printer-&gt;nextElement&quot;
    </DIV>
    <DIV>
      is executed on the second pass. &nbsp;Further, a NullReferenceExcepti=
on is
    </DIV>
    <DIV>
      thrown on the first iteration through the loop by simply invoking
    </DIV>
    <DIV>
      &quot;Console.WriteLine(&quot;PrinterInfo: {0}, {1}&quot;, pl.Name, =
pl.Uri)&quot;.
    </DIV>
    <DIV>
      I have tried several attributes on the structure elements with no =
change
    </DIV>
    <DIV>
      in behavior. &nbsp;I believe the problem is in the marshalling =
attributes, but
    </DIV>
    <DIV>
      I have yet to discover how to examine the memory in mono on linux.
    </DIV>
    <DIV>
      Installing/configuring a windows client and running/debugging there
    </DIV>
    <DIV>
      may be the easiest path.
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      Thanks again for the help.
    </DIV>
    <DIV>
      Jim
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      // interop struct
    </DIV>
    <DIV>
      [ StructLayout(LayoutKind.Sequential) ]
    </DIV>
    <DIV>
      private&#65533;unsafe&#65533;struct&#65533;InternalPrinterList
    </DIV>
    <DIV>
      {
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, =
SizeConst=3D1024)]
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;public string printerUri;
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, =
SizeConst=3D1024)]
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;public string printerCupsUri;
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, =
SizeConst=3D1024)]
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;public string printerName;
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;[MarshalAs(UnmanagedType.ByValTStr/*LPStr*/,SizeCon=
st=3D81)]
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;public&#65533;string&#65533;printerMakeModel;
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;[MarshalAs(UnmanagedType.U4)]
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;public InternalPrinterList *nextElement;
    </DIV>
    <DIV>
      }
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      // Convert linked list constructed by unmanaged code to
    </DIV>
    <DIV>
      // array of user-visible PrinterList objects.
    </DIV>
    <DIV>
      public static unsafe PrinterList[] ListLocalPrinters()
    </DIV>
    <DIV>
      {
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;IntPtr list =3D IntPtr.Zero;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;try
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListLocalPrinters(ref list);
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InternalPrinterList* printer =3D =
(InternalPrinterList *)list;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ArrayList printers =3D new =
ArrayList();
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (printer !=3D null)
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrinterList pl =
=3D new PrinterList();
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pl.Uri =3D =
printer-&gt;printerUri;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pl.CupsUri =3D =
printer-&gt;printerCupsUri;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pl.Name =3D =
printer-&gt;printerName;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pl.MakeModel =
=3D printer-&gt;printerMakeModel;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// throws =
NullReferenceException=20
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLi=
ne(&quot;PrinterInfo: {0}, {1}&quot;, pl.Name, pl.Uri);
    </DIV>
    <DIV>&nbsp;</DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printers.Add(pl=
);
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Something =
not right here as we will go through again
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// even when =
list contains only 1 element.
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printer =3D =
printer-&gt;nextElement;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrinterList[] rval =3D new =
PrinterList[printers.Count];
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printers.CopyTo(rval);
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return rval;
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;catch (Exception e)
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new PrinterList[0];
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;finally
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;{
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (list !=3D IntPtr.Zero)
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FreeLocalPrinte=
rList(list);
    </DIV>
    <DIV>
      &nbsp;&nbsp;&nbsp;}
    </DIV>
    <DIV>
      }
    </DIV>
  </body>
</html>

--=__Part6F4F1C04.0__=--