IDL type string maps to char*
in C++. Such C++ pointers must point to null-terminated character strings. In addition, a helper class, CORBA::string_var
, is also defined to make the memory management of strings easier.
All strings passed as out
or inout
parameters or return values to IDL operations, or returned as attribute values, must be allocated using one of the following two C++ functions that are defined in the CORBA scope:
// In namespace (or class) CORBA char *string_dup (const char*); char *string_alloc(CORBA::ULong len);
Note the length excludes the space for the terminating '\0' character. CORBA::string_alloc( )
returns zero if it cannot allocate the required storage.
CORBA::string_alloc( )
allocates space for a string, and any function (such as strcpy( )
) can be used to initialize this space. CORBA::string_dup( )
allocates space, and copies the specified string parameter into this space. For example, strings can be allocated as follows:
char* p1 = CORBA::string_dup("hello"); char *p2 = CORBA::string_alloc(6); strcpy(p2,"hello2");
Strings allocated with CORBA::string_alloc( )
or CORBA::string_dup( )
must be deallocated using:
void string_free(char*);
For example:
CORBA::string_free(pl); CORBA::string_free(p2);
It is not legal to use the normal new and delete operators.
Another reason for string_alloc( )
, string_dup( )
, and string_free( )
is that they allow an ORB to have complete control of memory allocation. For example, it can allocate all of the out parameters for an operation in a contiguous storage block, and only deallocate this block when the client is finished using all of the parameters.
The class CORBA::String_var
is defined as a helper class to aid the memory management of strings for clients and servers. Note the capital letter in the type name CORBA::String_var
and the small letter in function names such as CORBA::string_dup
.
CORBA::String_var
is similar to char*
in that an instance of CORBA::String_var
references a null-terminated character string; it differs in that the destructor of CORBA::String_var
deallocates the referenced character string. Hence, the following code does not leak memory:
CORBA::String_var s1 CORBA::string_dup("hello");
When s1
goes out of scope its destructor deallocates the string.
A CORBA::String_var
variable owns the memory that it points to, that is, it deallocates it in its destructor.
Typical usages of CORBA::String_var
are shown in the following subsections.
You are not required to use CORBA::String_var
, it is provided only for convenience. Use of CORBA::String_var
code may simplify programming although you must be careful never to assign a string pointer to a CORBA::String_var
variable unless it is safe for that variable to own the string.
Class CORBA::String_var
defines the usual copy constructor and operator=( );
both of which make a deep copy; that is, they copy the string value. Class CORBA::String_var
also provides operator which can be used to index into a string it returns the char value at a given index.
CORBA::String_var
has a conversion to and from char*, as shown in the following code:
char* p1 = char* p2 = CORBA::String_var v1 = CORBA::String_var v2 =
The following statements should be read separately, and not as a statement sequence:
p1 = p2; p1 = v2; v1 = p2 v1 = v2;
Only the final statement makes a copy of the string. An assignment that involves a char* does not make a copy, only an assignment that involves two CORBA::String_var
variables makes a copy of the string, because each CORBA::String_var
must own its own string.
An assignment into a CORBA::String_var
deallocates the string that the CORBA::Stringvar
previously pointed to.
The following statement is likely to cause a runtime error because a literal string cannot be owned by the CORBA::String_var
(because it cannot be freed), and yet it is not copied:
CORBA::String_var v3 = "literal";
Instead, the following should be written:
CORBA::String_var v3 = CORBA::string_dup("literal");
CORBA::String_var
can simplify the management of strings. But remember that a CORBA::String_var
variable expects to own the string it references. Be careful, therefore, not to assign a string to such a variable when it is clear that it cannot own the string.
As well as showing typical uses of CORBA::String_var
variables, the rest of this section describes the general memory management rules and shows some inappropriate uses where this ownership rule is broken.
The formal parameter and return types for IDL strings are shown in the following table. Note that CORBA::String_var
is not used by the IDL compiler; it is for application use only.
IDL type | in | out | inout | return |
---|---|---|---|---|
const char* |
const S& |
char*& |
char*& |
char* |
For in
parameters, the target object is given a pointer that it cannot change. For out
parameters, the target object is given a pointer that it can change to point to a new string (that the caller assumes ownership of). The same applies to inout
parameters. A return value is passed as a pointer to a string (that the caller assumes ownership of).
All strings passed as out or inout parameters or return values to IDL operations, or returned as attribute values, must be allocated using CORBA::string_dup( )
or CORBA::string_alloc( )
and freed using CORBA::string_free( )
. This does not apply to in parameters because the client retains ownership of the strings passed, it can decide how to allocate and deallocate strings.
Note: Be careful not to pass or return a zero pointer. Instead, pass an empty string.
Memory management rules are a contract between the caller of a function and the actions of the function itself. In CORBA, there may be a number of contracts, for example, between the client code and the ORB on the client side, and between the ORB on the server side and the target object.
In cases where the client and target object are in the same address space, the contract is directly between the client and the target object. When the client and target object are in different address spaces, the ORB on the client and server cooperate to ensure that the rules are the same as in the local case. This is an important aim of CORBA and one that has had a significant effect on the memory management rules.
The memory management rules for strings are straightforward, and they can be summarized as described in the following sections.
The caller retains ownership of the string passed in. The target object is given temporary access to the string, but not ownership of it. The string can be allocated and deallocated in any way that the client wants (on the stack, using new and delete, or using the CORBA functions string_dup( )
, string_alloc( )
, and string_free( )
).
With return values, attribute values, and out parameters, the target object gives up ownership of the returned string, and the caller is given ownership of it and hence it should deallocate it. Because the string returned by the target object will be deallocated, typically, it will copy a string using string_dup( )
, or string_alloc( )
and strcpy
and return this copy to the caller, or it will construct a string specifically to return to the caller. It should never return the only copy of a string that it wants to keep. The caller must assume that the string has been allocated in read-only memory, and cannot change it in place.
The ownership of the string is temporarily passed to the target object. After the call, the caller retains ownership of the string (but, of course, the string may have changed to a new location and/or value). If the target object does not need to change the string's memory location, it should not deallocate the string passed to it.
If it does need to change the string then it should call string_free( )
on the old string, and allocate a new string using string_dup( )
or string_alloc( )
. After the call, it gives up ownership of the new string. The target object is allowed to modify the inout string or deallocate it and allocate a new one that is returned to the caller.
The client-side rules can be summarized as follows: if a client receives a pointer from a call, it must deallocate the space. Most of the server-side rules can be summarized by the statement that it loses ownership of strings it passes to the caller.