comp.lang.ada
 help / color / mirror / Atom feed
* 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  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 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 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