| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| 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 |
|
#2
| |||
| |||
| 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 . @ . |
|
#3
| |||
| |||
| 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; |
|
#4
| |||
| |||
| 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 . @ . |
|
#5
| |||
| |||
| 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 |
|
#6
| |||
| |||
| >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.." |
|
#7
| |||
| |||
| 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 |
|
#8
| |||
| |||
| (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 . @ . |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.