* C chars_ptr STORAGE_ERROR in Imported function @ 2008-08-22 8:36 Kim Rostgaard Christensen 2008-08-22 9:03 ` Niklas Holsti 2008-08-22 18:48 ` anon 0 siblings, 2 replies; 8+ messages in thread From: Kim Rostgaard Christensen @ 2008-08-22 8:36 UTC (permalink / raw) Hello there I am in progress of binding the pcap c library to ada, it is a part of a school project. And for that i need a funtion that modifies a parameter to a function like so: char *pcap_lookupdev(char *); I have figured out this much: function pcap_lookupdev(errbuff : Interfaces.C.Strings.Chars_Ptr) return Interfaces.C.Strings.Chars_Ptr; pragma Import (C, pcap_lookupdev, "pcap_lookupdev"); This works in the sense that running it as root returns the device found, but when I run it as normal user I get raised STORAGE_ERROR : stack overflow (or erroneous memory access) Do I need to declare the buffer and then then pass its c pointer to the function? It is declared like this in a c example: char errbuf[PCAP_ERRBUF_SIZE]; Best Kim Rostgaard Christensen ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C chars_ptr STORAGE_ERROR in Imported function 2008-08-22 8:36 C chars_ptr STORAGE_ERROR in Imported function Kim Rostgaard Christensen @ 2008-08-22 9:03 ` Niklas Holsti 2008-08-22 9:55 ` Kim Rostgaard Christensen 2008-08-22 18:48 ` anon 1 sibling, 1 reply; 8+ messages in thread From: Niklas Holsti @ 2008-08-22 9:03 UTC (permalink / raw) Kim Rostgaard Christensen wrote: > Hello there > > I am in progress of binding the pcap c library to ada, it is a part of a > school project. And for that i need a funtion that modifies a parameter > to a function like so: > > char *pcap_lookupdev(char *); > ... > > Do I need to declare the buffer and then then pass its c pointer to the > function? That is certainly my interpretation of the "man" text: char *pcap_lookupdev(char *errbuf) pcap_lookupdev() returns a pointer to a network device suitable for use with pcap_open_live() and pcap_lookupnet(). If there is an error, NULL is returned and errbuf is filled in with an appropriate error message. There is no hint that pcap_lookupdev() itself allocates the errbuf; it just puts something in the caller-provided errbuf. And no doubt places a NUL terminator after the message. HTH -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C chars_ptr STORAGE_ERROR in Imported function 2008-08-22 9:03 ` Niklas Holsti @ 2008-08-22 9:55 ` Kim Rostgaard Christensen 2008-08-22 11:43 ` Niklas Holsti 0 siblings, 1 reply; 8+ messages in thread From: Kim Rostgaard Christensen @ 2008-08-22 9:55 UTC (permalink / raw) Niklas Holsti wrote: > Kim Rostgaard Christensen wrote: >> Hello there >> >> I am in progress of binding the pcap c library to ada, it is a part of a >> school project. And for that i need a funtion that modifies a >> parameter to a function like so: >> >> char *pcap_lookupdev(char *); >> > ... >> >> Do I need to declare the buffer and then then pass its c pointer to >> the function? > > That is certainly my interpretation of the "man" text: > > char *pcap_lookupdev(char *errbuf) > > pcap_lookupdev() returns a pointer to a network device > suitable for use with pcap_open_live() and pcap_lookupnet(). > If there is an error, NULL is returned and errbuf is filled > in with an appropriate error message. > > There is no hint that pcap_lookupdev() itself allocates the errbuf; it > just puts something in the caller-provided errbuf. And no doubt places a > NUL terminator after the message. > > HTH > the following gives me *** glibc detected *** double free or corruption (out): 0x0804d830 *** raised PROGRAM_ERROR : unhandled signal procedure Lookup_Device is function pcap_lookupdev(ebuff : Interfaces.C.Strings.Chars_Ptr) return Interfaces.C.Strings.Chars_Ptr; pragma Import (C, pcap_lookupdev, "pcap_lookupdev"); Device : Interfaces.C.Strings.Chars_Ptr; Errbuf_ptr : Interfaces.C.Strings.Chars_Ptr; Errbuf : Char_Array(1 .. 256); -- the defined buffer size begin Errbuf_Ptr := New_Char_Array(Errbuf); Device := pcap_lookupdev(Errbuf_ptr); Ada.Text_IO.Put_Line(Value(Device)); end Lookup_Device; ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C chars_ptr STORAGE_ERROR in Imported function 2008-08-22 9:55 ` Kim Rostgaard Christensen @ 2008-08-22 11:43 ` Niklas Holsti 2008-08-22 22:54 ` Kim Rostgaard Christensen 0 siblings, 1 reply; 8+ messages in thread From: Niklas Holsti @ 2008-08-22 11:43 UTC (permalink / raw) Kim Rostgaard Christensen wrote: > Niklas Holsti wrote: > >> Kim Rostgaard Christensen wrote: >> >>> Hello there >>> >>> I am in progress of binding the pcap c library to ada, it is a part of a >>> school project. And for that i need a funtion that modifies a >>> parameter to a function like so: >>> >>> char *pcap_lookupdev(char *); >>> ... > > the following gives me > *** glibc detected *** double free or corruption (out): 0x0804d830 *** > > raised PROGRAM_ERROR : unhandled signal > > procedure Lookup_Device is > function pcap_lookupdev(ebuff : Interfaces.C.Strings.Chars_Ptr) > return Interfaces.C.Strings.Chars_Ptr; > pragma Import (C, pcap_lookupdev, "pcap_lookupdev"); > > Device : Interfaces.C.Strings.Chars_Ptr; > Errbuf_ptr : Interfaces.C.Strings.Chars_Ptr; > Errbuf : Char_Array(1 .. 256); -- the defined buffer size > begin The problem is here: > Errbuf_Ptr := New_Char_Array(Errbuf); New_Char_Array allocates a new char_array object, containing only the NUL-terminated string that is in Errbuf at this time. Since you have left Errbuf uninitialized, this may be a lot less than 256 characters, so the errors are probably due to buffer overflow somewhere in the pcap library where it tries to put an error message into the char_array that Errrbuf_Ptr points to, but this char_array is too small. If you want to continue with New_Char_Array, you should initialize Errbuf to contain a 256-character string: Errbuf : Char_Array (1 .. 256) := ( others => Interfaces.C.To_C (' ')); or perhaps neater, but more complex, a NUL-terminated 255-character string: Errbuf : Char_Array (1 .. 256) := ( 1 .. 255 => Interfaces.C.To_C (' '), 256 => Interfaces.C.nul); Then New_Char_Array(Errbuf) will create a 256-character char_array that has room for the error message. (It works for me.) If you use New_Char_Array you should also deallocate the new char_array by calling Interfaces.C.Strings.Free (Errbuf_Ptr) at a suitable point, when you no longer need this char_array. I think it would be better to use the To_Chars_Ptr function, which makes a chars_ptr that points to Errbuf itself, without allocating another char_array, so there is no need to Free anything. This also needs a change in the declaration of Errbuf: Errbuf : aliased Char_Array := (1 .. 256 => Interfaces.C.nul); The initial values (here nul) are irrelevant, as long as there are 256 of them. Then you replace the call of New_Char_Array with To_Chars_Ptr: Errbuf_Ptr := To_Chars_Ptr (Errbuf'Unchecked_Access, False); followed by: > Device := pcap_lookupdev(Errbuf_ptr); Also note that this can result in Device being a null pointer, which will cause an error in the following: > Ada.Text_IO.Put_Line(Value(Device)); so better check, like this: if Device = Null_Ptr then Put_Line ("Null device: " & Value (Errbuf_Ptr)); else Put_Line ("Found device: " & Value (Device)); end if; HTH -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C chars_ptr STORAGE_ERROR in Imported function 2008-08-22 11:43 ` Niklas Holsti @ 2008-08-22 22:54 ` Kim Rostgaard Christensen 0 siblings, 0 replies; 8+ messages in thread From: Kim Rostgaard Christensen @ 2008-08-22 22:54 UTC (permalink / raw) Niklas Holsti wrote: ... > I think it would be better to use the To_Chars_Ptr function, which makes > a chars_ptr that points to Errbuf itself, without allocating another > char_array, so there is no need to Free anything. This also needs a > change in the declaration of Errbuf: > > Errbuf : aliased Char_Array := (1 .. 256 => Interfaces.C.nul); > ... > Errbuf_Ptr := To_Chars_Ptr (Errbuf'Unchecked_Access, False); > > followed by: > >> Device := pcap_lookupdev(Errbuf_ptr); > ... > HTH > This works like a charm, thanks a lot. KRC ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C chars_ptr STORAGE_ERROR in Imported function 2008-08-22 8:36 C chars_ptr STORAGE_ERROR in Imported function Kim Rostgaard Christensen 2008-08-22 9:03 ` Niklas Holsti @ 2008-08-22 18:48 ` anon 2008-08-22 21:55 ` tmoran 2008-08-23 10:11 ` Niklas Holsti 1 sibling, 2 replies; 8+ messages in thread From: anon @ 2008-08-22 18:48 UTC (permalink / raw) Because Char_Prt in "Interfaces.C.Strings" is a private Ada type that C function does not understand. You need to use "Interfaces.C.Pointer" package to build a C Char_Ptr pointer package. And use those functions, etc. A possibility that most teachers may frown about, but it does work is to switch the Ada pointers to "System.Address" and pass to the C functions.. Check out the "Interfaces.C.Extensions.ads" to see how the "void" and "void *" are handled, if the teachers dislike the idea. In <g8ltqo$7ir$1@jacob-sparre.dk>, Kim Rostgaard Christensen <krc@greenpc.dk> writes: >Hello there > >I am in progress of binding the pcap c library to ada, it is a part of a >school project. And for that i need a funtion that modifies a parameter >to a function like so: > >char *pcap_lookupdev(char *); > >I have figured out this much: > > function pcap_lookupdev(errbuff : Interfaces.C.Strings.Chars_Ptr) >return Interfaces.C.Strings.Chars_Ptr; > pragma Import (C, pcap_lookupdev, "pcap_lookupdev"); > >This works in the sense that running it as root returns the device >found, but when I run it as normal user I get > >raised STORAGE_ERROR : stack overflow (or erroneous memory access) > >Do I need to declare the buffer and then then pass its c pointer to the >function? > >It is declared like this in a c example: >char errbuf[PCAP_ERRBUF_SIZE]; > >Best >Kim Rostgaard Christensen ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C chars_ptr STORAGE_ERROR in Imported function 2008-08-22 18:48 ` anon @ 2008-08-22 21:55 ` tmoran 2008-08-23 10:11 ` Niklas Holsti 1 sibling, 0 replies; 8+ messages in thread From: tmoran @ 2008-08-22 21:55 UTC (permalink / raw) >A possibility that most teachers may frown about, but it does work is to >switch the Ada pointers to "System.Address" and pass to the C functions.. That should be ".., but it may work on some versions of some compilers.." ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C chars_ptr STORAGE_ERROR in Imported function 2008-08-22 18:48 ` anon 2008-08-22 21:55 ` tmoran @ 2008-08-23 10:11 ` Niklas Holsti 1 sibling, 0 replies; 8+ messages in thread From: Niklas Holsti @ 2008-08-23 10:11 UTC (permalink / raw) (Top posting by "anon" changed to bottom style...) anon wrote: > In <g8ltqo$7ir$1@jacob-sparre.dk>, Kim Rostgaard Christensen > <krc@greenpc.dk> writes: > >>Hello there >> >>I am in progress of binding the pcap c library to ada, it is a >>part of a school project. And for that i need a funtion that >>modifies a parameter to a function like so: >> >>char *pcap_lookupdev(char *); >> >>I have figured out this much: >> >> function pcap_lookupdev(errbuff : Interfaces.C.Strings.Chars_Ptr) >> return Interfaces.C.Strings.Chars_Ptr; >> pragma Import (C, pcap_lookupdev, "pcap_lookupdev"); >> >>This works in the sense that running it as root returns the >>device found, but when I run it as normal user I get >>raised STORAGE_ERROR : stack overflow (or erroneous memory >>access) >> >>Do I need to declare the buffer and then then pass its c pointer >>to the function? anon wrote: > Because Char_Prt in "Interfaces.C.Strings" is a private Ada > type that C function does not understand. No, that's wrong. RM B.3.1(1) says that ...the private type chars_ptr corresponds to a common use of "char *" in C programs, and an object of this type can be passed to a subprogram to which pragma Import(C,...) has been applied, and for which "char *" is the type of the argument of the C function. I think Kim's choice of chars_ptr for this parameter is correct. The error was firstly in the use of an uninitialized parameter of this type (default initialized to Null_Ptr), and secondly in using New_Char_Array on an uninitialized char_array, making New_Char_Array allocate a smaller new buffer than was needed to hold the error message from pcap_lookupdev(). Thus, pcap_lookupdev() was called with incorrect values of its parameter, not with an incorrect type of parameter. Similar errors could have been made in a C function calling pcap_lookupdev() with a C parameter of type "char *". > You need to use "Interfaces.C.Pointer" package to build a C > Char_Ptr pointer package. That might work, too, but Interfaces.C.Strings is the right tool for pcap_lookupdev() since the parameter really is a NUL-terminated C-style string. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-08-23 10:11 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-08-22 8:36 C chars_ptr STORAGE_ERROR in Imported function Kim Rostgaard Christensen 2008-08-22 9:03 ` Niklas Holsti 2008-08-22 9:55 ` Kim Rostgaard Christensen 2008-08-22 11:43 ` Niklas Holsti 2008-08-22 22:54 ` Kim Rostgaard Christensen 2008-08-22 18:48 ` anon 2008-08-22 21:55 ` tmoran 2008-08-23 10:11 ` Niklas Holsti
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox