[omniORB] sequence<string>::operator[]
Bruce Visscher
visschb@rjrt.com
Wed, 12 Apr 2000 14:33:57 -0400
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