* 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