[omniORB] sequence<string>::operator[]

Bruce Visscher visschb@rjrt.com
Wed, 12 Apr 2000 16:22:01 -0400


Sorry to reply to my own post, but I have another question about this.

Apparently, the operator[] for sequences of strings worked under 2.7.1 on Compaq
C++ 5.6/OpenVMS VAX.  I am having to work around this for 2.8.0 by using the
getbuf/freebuf interface (ick).

Under 2.7.1, sequences of strings were a typedef as CORBA::String_member.  Also,
the implementation of CORBA::String_member was much simpler (just a pointer, no
reference, no flag).  What problems or enhancements was the new implementation
intended to address?

Bruce Visscher wrote:
> 
> Hello all,
> 
> The code at the end of this message was adapted from [Henning & Vinoski], page
> 183.  I added the "Const is broken" test.
> 
> When I compile and run this on OpenVMS Alpha using Compaq C++ 6.2 and omniORB
> 2.8.0, I get:
> 
> myseq[0] = "first"
> myseq[1] = "second"
> myseq[2] = "third"
> myseq[3] = "fourth"
> 
> myseq[0] = "first"
> myseq[1] = "second element"
> myseq[2] = "third"
> myseq[3] = "4th"
> myseq[4] = "5th"
> 
> myseq[0] = "Const is broken"
> myseq[1] = "second element"
> myseq[2] = "third"
> myseq[3] = "4th"
> myseq[4] = "5th"
> 
> On OpenVMS VAX using Compaq C++ 5.6C and either omniORB 2.8.0 or omniORB 3.0 I
> get:
> 
> myseq[0] = ""
> myseq[1] = ""
> myseq[2] = ""
> myseq[3] = ""
> 
> myseq[0] = ""
> myseq[1] = ""
> myseq[2] = ""
> myseq[3] = ""
> myseq[4] = ""
> 
> myseq[0] = ""
> myseq[1] = ""
> myseq[2] = ""
> myseq[3] = ""
> myseq[4] = ""
> 
> I'm actually not too concerned about the const-correctness problem on Alpha.
> This code is relying on an implementation artifact (CORBA::String_member) rather
> than something in the CORBA standard.  BTW, since String_member is non-standard
> should this even be in the CORBA namespace?   In any case, I think the problem
> here is the compiler is being "too" agressive with optimization (but don't know
> that it's wrong).
> 
> I believe the problem with the 5.6 compiler on the VAX is that the
> implementation of _CORBA_Sequence__String::operator[] (non-const) relies on a
> compiler optimization being performed:
> 
>   inline ElemT operator[] (_CORBA_ULong i) {
>     if( i >= pd_len )  _CORBA_bound_check_error();
>     return ElemT(pd_data[i],pd_rel);
>   }
> 
> I believe that this is another form of copy initialization which is defined as
> performing a copy which the compiler is allowed (but not required) to optimize
> away.  If the copy is performed then we get an independent String_member and the
> assignment modifies a temporary that no longer has any relation to the sequence
> member.
> 
> Is this analysis correct?  Do other platforms experience this problem?
> 
> ---------------------------------- strseq.idl ----------------------------------
> typedef sequence<string> StrSeq;
> ---------------------------------- strseq.idl ----------------------------------
> wpsys2[.STRINGSEQ]> @home:outputforcut "strseq.cc"
> ---------------------------------- strseq.cc -----------------------------------
> #include <iostream>
> #include "StrSeq.hh"
> 
> #if defined(__DECCXX) && (__DECCXX_VER < 60000000)
> #define std
> #endif
> 
> int main() {
>     char const* values[] = { "first", "second", "third", "fourth" };
> 
>     StrSeq myseq;
> 
>     // Create four empty strings
>     myseq.length(4);
>     {   //  redundant scope for broken compilers
>         for (CORBA::ULong i = 0; i < myseq.length(); i++) {
>             CORBA::String_member tmp(myseq[i]);
>             tmp = values[i];   //       Deep copy
>         }
>     }
> 
>     //  Print current copy.
>     {   //  redundant scope for broken compilers
>         for (CORBA::ULong i = 0; i < myseq.length(); i++)
>             std::cout << "myseq[" << i << "] = \"" << myseq[i] << "\"" << std::e
> ndl;
>     }
>     std::cout << std::endl;
> 
>     // Change the second element (deallocates "second")
>     myseq[1] = CORBA::string_dup("second element");
> 
>     // Truncate to three elements
>     myseq.length(3);                // Deallocates "fourth"
> 
>     // Grow to five elements (add two empty strings)
>     myseq.length(5);
> 
>     // Initialize appnded elements
>     myseq[3] = CORBA::string_dup("4th");
>     myseq[4] = CORBA::string_dup("5th");
> 
>     // Print contents once more
>     {   //  redundant scope for broken compilers
>     for (CORBA::ULong i = 0; i < myseq.length(); i++)
>         std::cout << "myseq[" << i << "] = \"" << myseq[i] << "\"" << std::endl;
>     }
>     std::cout << std::endl;
> 
>     StrSeq const& constref(myseq);
>     CORBA::String_member x=constref[0];
>     x="Const is broken";
>     {   //  redundant scope for broken compilers
>     for (CORBA::ULong i = 0; i < myseq.length(); i++)
>         std::cout << "myseq[" << i << "] = \"" << myseq[i] << "\"" << std::endl;
>     }
> }
> ---------------------------------- strseq.cc -----------------------------------
> 
> Bruce Visscher