From: Jeffrey Carter <spam@spam.com>
Subject: Re: Modes (was unbounded_string)
Date: Fri, 10 Oct 2003 19:06:00 GMT
Date: 2003-10-10T19:06:00+00:00 [thread overview]
Message-ID: <sqDhb.6123$dn6.5019@newsread4.news.pas.earthlink.net> (raw)
In-Reply-To: <mailman.60.1065773352.25614.comp.lang.ada@ada-france.org>
Andrew Carroll wrote:
>>>For all other types, the compiler chooses the parameter
>>>mode best suited to the type.
If I wrote that, then I made an error. It should be, "the compiler
chooses the parameter passing mechanism best suited to the type."
> package x is
> type x;
> type xptr is access x;
> type x is tagged limited record
> head: nodeptr;
> something: unbounded_string;
> end record;
>
> --creates a new node to put into the 'head' list.
> --new node is created from information in token.
> --token has nothing to do with the 'something' variable
> --declared in the record above.
> procedure add(this: xptr; token: unbounded_string);
>
> end x;
>
> So, with the above code "example", xptr is passed as an 'in'
> or 'in out' mode at the add procedure?
Since you didn't specify the mode, the mode is "in". That has nothing to
do with the parameter passing mechanism.
> Are you saying that I should use just x and not xptr as the
> parameter so that the compiler will choose the correct mode?
Since you seem to be dealing with a dynamically allocated structure,
then pointers are probably fine for implementing the structure. But
there seems to no need for the client to pass in a value of type X or
Xptr. There is even no need for the client to know about the details of
these types. Instead, you should have a Head_List type which is
[limited] private; the client should pass in an object of type Head_List
(mode in out, so it can be modified), and a value of type
Unbounded_String to add to the Head_List. Add allocates a new node and
links it into the list. Head_List should probably be controlled so you
can manage its memory.
> If so, you recommend it because of deallocation issues?
Precisely. With the pointer type exposed, and the client required to use
it, the client becomes responsible for memory management and it has to
be scattered all over the client's code. It's practically impossible to
avoid errors that way. With the implementation hidden, all the memory
management is in one place. Getting it right is easier; finding and
fixing errors is easier. The client's code is simpler.
> Is there something in the code below that I missed about information
> hiding?
>
> Temp: gnat.os_lib.String_Access;
> ...
> Temp := gnat.os_lib.getenv("QUERY_STRING");
> ...
> ---------------------------------------
> -- ready to use Temp for something else
> ---------------------------------------
> Temp := gnat.os_lib.getenv("SOME_OTHER_VARIABLE");
Since GNAT.OS_Lib.Getenv returns type String_Access, you have to use
String_Access if you want to use Getenv. But note the description of
Getenv from GNAT.OS_Lib:
-- Get the value of the environment variable. Returns an access
-- to the empty string if the environment variable does not exist
-- or has an explicit null value (in some operating systems these
-- are distinct cases, in others they are not; this interface
-- abstracts away that difference. The argument is allocated on
-- the heap (even in the null case), and needs to be freed explicitly
-- when no longer needed to avoid memory leaks.
Your code leaks memory, because the package has dumped the memory
management onto the client, and you haven't done it. This is not, in my
opinion, a good way to do this. Getenv should return a string, and deal
with any memory management issues.
Note that Kazakov's versions using Unbounded_String and renaming the
string pointed to also leak memory.
> Considering the code above, what is the "Ada idiom" to "resize" a String
> without pointers and dynamic allocation? In other words; what "Ada
> idiom" code would you write to do the same thing I did, without pointers
> and dynamic allocation? You don't have to write the code, a good
> reading reference would be okay.
If you have to use GNAT.OS_Lib.Getenv, I would do something like
declare
Temp : String_Access := Getenv;
Env : constant String := Temp.all;
begin
Free (Temp);
-- Deal with Env
end;
If you're speaking in general about having a string object that can hold
values of different lengths, then you want to use Ada.Strings.[Un]Bounded.
Something : Unbounded_String;
function Get return String is ...;
...
Something := To_Unbounded_String (Get);
...
-- Repeat as desired
Very often in Ada, though, you can create [constant] Strings as you go,
eliminating the need for [Un]Bounded_String.
--
Jeff Carter
"C++ is like jamming a helicopter inside a Miata
and expecting some sort of improvement."
Drew Olbrich
51
next prev parent reply other threads:[~2003-10-10 19:06 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20031010074015.761204C40C1@lovelace.ada-france.org>
2003-10-10 8:27 ` Modes (was unbounded_string) Andrew Carroll
2003-10-10 9:15 ` Dmitry A. Kazakov
2003-10-11 7:16 ` Simon Wright
2003-10-13 9:28 ` Dmitry A. Kazakov
2003-10-10 15:18 ` Stephen Leake
2003-10-10 16:21 ` Martin Dowie
2003-10-14 18:47 ` Craig Carey
2003-10-10 19:06 ` Jeffrey Carter [this message]
2003-10-13 9:33 ` Dmitry A. Kazakov
2003-10-13 9:40 ` Stephane Richard
2003-10-13 10:12 ` Dmitry A. Kazakov
2003-10-15 2:16 ` Warren W. Gay VE3WWG
2003-10-15 3:36 ` Jeff C,
2003-10-16 16:45 ` Warren W. Gay VE3WWG
[not found] <20031010094017.680474C40C1@lovelace.ada-france.org>
2003-10-10 10:58 ` Andrew Carroll
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox