Wednesday, April 14, 2004 - Posts

reopen fstreams, bug?

Re-open a fstream may fail... call clear() between close() and open()!

http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4_iostreamclear

posted by wenyang with 0 Comments

Suggestions about Improving Efficiency (gcc)

During the migration of CorbaFreeDynaMIT, we have noticed that some previous code may more or less decrease the efficiency. We are not talking about the algorithm at this time, though it should be more critical and significant.

Anyway, here are a few "rules of thumb" to avoid defect.

  • Remove unnecessary code from loop. For example, making a function call to check the size of a list during the loop can be taken out of the loop if the size is not going to change during the loop.
  • Use header files properly.To minimize the time we have to wait on the compiler, it's good to only include the headers we really need. Many people simply include iostream when they don't need to -- and that can penalize the runtime as well. (http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#10)
  • Use "\n" in output stream other than std::endl whenever possible. std::endl not only sends out a new line, but also flush the stream, sending out the output immediately, and the buffer is lost. The next time we add something to the stream, we have to re-allocate the buffer, which is time-consuming and ususally unnecessary.
posted by wenyang with 0 Comments

Notes to Migration of CorbaFreeDynaMIT (6)

Iterators

Iterators are a generalization of pointers: they are objects that point to other objects. In most situations we could instead use a pointer when an iterator is required, and even under some circumstance, the compiler will actually optimize iterators into pointers when creating the object codes. Iterators, however, are not necessarily implemented by pointers. For example, vector::iterator is not T*; string::iterator is not char*. Hence converting iterators to pointers is considered dangerous, and is likely to make our code broken.

The STL offers several predefined iterators, with different behavior. For example, the input iterators only guarantee read access. Selecting the correct type of iterators is one of the tasks we must face when migrating CorbaFreeDynaMIT.

Where does it occur? Most classes that use STL containers (vectors, pair, etc.) For example, in the getODID member function of class dtaMappingOD, using a writable iterator will cause an error: "invalid conversion from 'const idlOrigDestID* const' to 'idlOrigDestID*'."

Another example is we should not test whether a iterator is null pointer or not. The following code is invalid:

std::vector::iterator jIterator;

for( jIterator= iIterator->begin(); jIterator != iIterator->end(); jIterator++ )

{

if( jIterator ) { // i.e., if (jIterator != NULL )

// do something...

}

}
How to fix: Use const_iterator instead of the default iterator, and avoid unnecessary type conversion. Make sure we have include the proper header file, i.e.,

posted by wenyang with 0 Comments

Notes to Migration of CorbaFreeDynaMIT (5)

2.4 Stream formatting
The formating of stream is controled by so-called "flags". In the new c++ library, the data type for flags, defined as "__fmtflags" or "std::_Ios_Fmtflags" by the typedef statement, is in fact unsigned long integer.

For many member functions of the stream classes in STL, such as setf and flags, their arguments and/or return values are consequently of unsigned long type.

If we want to pass other types of data to those functions, we will have to cast (force type conversion) the data to unsigned long. In some situation, that might cause a problem.

Moreover, some functions in the stream classes change their definition. For instance, istream::unsetf no longer returns any value. We need to modify our code to adapt these changes.

Where does it occur? class Reader.

How to fix: We can either stick to our original data type, which is long, and use cast back and forth wherever it is needed, or change the function definition of our classes.

Changing public member function definitions for a class is error-prone and seldom suggested because it will change the interface of the class and thus might potentially affect all its clients, which make use of those public member functions.

Therefore currently we choose the first approach. We admit that conversion between unsigned long to long integers may cause some problem. In the long run we might still consider using the second approach.

posted by wenyang with 0 Comments

Notes to Migration of CorbaFreeDynaMIT (3)

2.2 Using std namespce

Since "std" is now a real namespace, required for many objects in GNU Standard C++ Library v3, or libstdc++-v3.

Most class or type identifiers and functions in the Standard Template Library (STL) are affected.

For example:

  • string, vector, list, map, multimap, etc.
  • i/o objects, e.g. cout, cerr, endl.
  • i/o formatting flags, eg hex, dec

Where does it occur? Most headers, source files. (*.h, *.cc, *.y)

How to fix: In most cases, we prefer adding the "std::" to wherever it is required. For example:

  • std::setiosflags( std::ios::showpoint | std::ios::fixed );
  • std::setprecision( 4 );
  • std::cout << std::flush;

This is the most explicit way. Also we need include the headers properly. For example, is required for std::cout, std::endl, etc.

We could also say "using namespace std;" somewhere before the call. This is the quick-butdirty fix, because it brings the whole of the std:: namespace into scope. Thus we should never do this in a header file, as every user of our header file will be affected by this decision.

posted by wenyang with 0 Comments

Notes to Migration of CorbaFreeDynaMIT (4)

2.3 From strstream to stringstream

The benefit of using stringstream include (a) we don't have to explicitly append ends to terminate the C-style character array, and (b) we don't have to mess with "freezing" functions or manage the memory ourselves. (We saw this in the original code of template std::string ToString( const TYPE &val ) from the file dtaSimulatedFlow.cc.)


Note: the stringstream.str() builds a string, not a char[] as was the case with strstream.str().
Thus we cannot to delete the buffer after use.

Where does it occur? Most classes that handles I/O, e.g. class Reader.

How to fix: std::strstream (similarly for ostrstream, istrstream) is replaced by std::stringstream (ostringstream and istringstream). Stringstreams are defined in the header .

In many cases, we simply use stringstream for output, thus we prefer std::ostringstream.

posted by wenyang with 0 Comments