|
|
|
This section gives an overview of libraries provided with HP aC++ and
how you can create and use your own libraries. This section is organized
into the following topics:
Refer to HP-UX Online Linker and Libraries User’s Guide for more information.
|
| HP aC++ Libraries |
|
In addition to the Standard HP-UX system libraries, HP aC++ provides
the following C++ libraries:
C++ Standard Library Change
Technical Corrigenda 1 has changed the STL function make_pair to
take their arguments by value instead of const reference. This change brings
the HP library into compliance if the enabling macro -D__HP_TC1_MAKE_PAIR
is specified at compile time. For binary compatibility reasons, the default
behavior is unchanged.
Standard C++ Library
The International Standards Organization (ISO) and the American National
Standards Institute (ANSI) have completed the process of standardizing
the C++ programming language. A major result of this standardization
process is the Standard C++ Library, a large and comprehensive
collection of classes and functions.
HP aC++ provides the Rogue Wave implementation of the ANSI/ISO
Standard C++ Library. This implementation includes the following features:
-
A subset of data structures and algorithms, updated from the
original library developed at Hewlett-Packard by Alex Stepanov
and Meng Lee and known as the C++ Standard Template Library
(STL). Note that the public domain C++ Standard Template Library
is not supported by this Standard C++ Library.
-
A templatized string class.
-
A templatized class for representing complex numbers.
-
A uniform framework for describing the execution environment,
through the use of a template class named numeric_limits
and specializations for each fundamental data type.
-
Memory management features.
-
Language support features.
-
Exception handling features.
Using the Standard C++ Library
Within a few years the Standard C++ Library will be
the standard set of classes and libraries delivered with all ANSI-conforming C++ compilers. Although the
design of a large portion of the Standard C++ Library is in many ways not object-oriented, C++ itself excels as
a language for manipulating objects. How do you integrate the library’s non-object-oriented architecture with
the language’s strengths for manipulating objects?
The key is to use the right tool for each task. Object-oriented design methods and programming techniques
are almost without peer as guideposts in the development of large complex software. For the large majority of
programming tasks, object-oriented techniques will remain the preferred approach. Products such as Rogue
Wave’s Tools.h++ Library which encapsulates the Standard C++ Library with a familiar object-oriented
interface, can provide you with the power and the advantages of object-orientation.
Use Standard C++ Library components directly when you need flexibility or highly efficient code. Use the
more traditional approaches to object-oriented design, such as encapsulation and inheritance, when you need
to model larger problem domains and knit all the pieces into a full solution. When you need to devise an
architecture for your application, always consider the use of encapsulation and inheritance to
compartmentalize the problem. But if you discover that you need an efficient data structure or algorithm for a
compact problem (the kind of problem that often resolves to a single class), look to the Standard C++ Library.
The library excels in the creation of reusable classes, where low-level constructs are needed, while traditional
OOP techniques really shine when those classes are combined to solve a larger problem.
In the future, most libraries will use the Standard C++ Library as their foundation. By using the Standard
C++ Library, either directly or through an encapsulation such as Tools.h++ Library, you help insure
interoperability. This is especially important in large projects that may rely on communication between
several libraries. A good rule of thumb is to use the highest encapsulation level available to you, but make
sure that the Standard C++ Library is available as the base for interlibrary communication and operation.
The C++ language supports a wide range of programming approaches because the problems we need to solve
require that range. The language, and now the Standard C++ Library that supports it, are designed to give
you the flexibility to approach each unique problem from the best possible angle. The Standard C++ Library,
when combined with more traditional OOP techniques, puts a very flexible tool into the hands of anyone
building a collection of C++ classes, whether those classes are intended to stand alone as a library or are
tailored to a specific task.
How the Standard C++ Library Differs from Other Libraries
A major portion of the Standard C++ Library is comprised of a collection
of class definitions for standard data structures and a collection of
algorithms commonly used to manipulate such structures. This part of the
library was derived from the Standard Template Library or STL. The
organization and design of this part of the library differs in almost
all respects from the design of most other C++ class libraries, because
it avoids encapsulation and uses almost no inheritance.
An emphasis on encapsulation is a key hallmark of object-oriented
programming. The emphasis on combining data and functionality into an
object is a powerful organization principle in software development;
indeed it is the primary organizational technique. Through the proper
use of encapsulation, even exceedingly complex software systems can be
divided into manageable units and assigned to various members of a team
of programmers for development.
Inheritance is a powerful technique for permitting code sharing and
software reuse, but it is most applicable when two or more classes share
a common set of basic features. For example, in a graphical user interface,
two types of windows may inherit from a common base window class, and
the individual subclasses will provide any required unique features.
In another use of inheritance, object-oriented container classes may
ensure common behavior and support code reuse by inheriting from a more
general class, and factoring out common member functions.
The designers of the STL decided against using an entirely
object-oriented approach, and separated the tasks to be performed using
common data structures from the representation of the structures
themselves. The STL was designed as a collection of algorithms and,
separate from these, a collection of data structures that could
be manipulated using the algorithms.
The Non-Object-Oriented Design of the Standard C++ Library
The portion of the Standard C++ Library derived from the STL was
purposely designed with an architecture that is not object-oriented. This
design has both advantages and disadvantages. Some of them are mentioned
below:
-
Smaller Source Code
There are approximately fifty
different algorithms and about a dozen major data structures. This
separation has the effect of reducing the size of source code, and
decreasing some of the risk that similar activities will have
dissimilar interfaces. Were it not for this separation, for example,
each of the algorithms would have to be re-implemented in each of the
different data structures, requiring several hundred more member
functions than are found in the present scheme.
-
Flexibility
One advantage of the separation of algorithms
from data structures is that such algorithms can be used with
conventional C++ pointers and arrays. Because C++ arrays are not
objects, algorithms encapsulated within a class hierarchy seldom
have this ability.
-
Efficiency
The STL in particular, and the Standard C++
Library in general, provide a low-level approach to developing
C++ applications. This low-level approach can be useful when
specific programs require an emphasis on efficient coding and
speed of execution.
-
Iterators: Mismatches and Invalidations
The Standard C++
Library data structures use pointer-like objects called
iterators to describe the contents of a container. Given the
library’s architecture, it is not possible to verify that these
iterator elements are matched, that is, that they are derived from
the same container. Using (either intentionally or by accident) a
beginning iterator from one container with an ending iterator from
another is a recipe for certain disaster. It is very important to
know that iterators can become invalidated as a result of a subsequent
insertion or deletion from the underlying container class. This
invalidation is not checked, and use of an invalid iterator can
produce unexpected results. Familiarity with the Standard C++ Library
will help reduce the number of errors related to iterators.
-
Templates: Errors and Code Bloat
The flexibility and
power of templatized algorithms is, with most compilers, purchased
at a loss of precision in diagnostics. Errors in the parameter lists
to generic algorithms will sometimes be manifest only as obscure
compiler errors for internal functions that are defined many levels
deep in template expansions. Again, familiarity with the algorithms
and their requirements is a key to successful use of the standard
library. Heavy reliance on templates can cause programs to
grow larger than expected. You can minimize this problem by
learning to recognize the cost of instantiating a particular
template class, and by making appropriate design decisions.
As compilers become more and more fluent in templates,
this will become less of a problem.
-
Multithreading Problems
The Standard C++ Library must be used
carefully in a multithreaded environment. Iterators, because they exist
independently of the containers they operate on, cannot be safely
passed between threads. Since iterators can be used to modify a
non-const container, there is no way to protect such a container if
it spawns iterators in multiple threads. Use thread-safe wrappers,
such as those provided by Tools.h++ Library, if you need to access
a container from multiple threads.
Standard C++ Library Reference
The Standard C++ Library Reference provides an alphabetical listing of
all of the classes, algorithms, and function objects in the prior
Rogue Wave implementation of the Standard C++ Library.
It is provided as HTML formatted files. You can view these files with
an HTML browser by opening the file /opt/aCC/html/libstd/ref.htm.
Incompatibilities Between the Library and the Standard
As the ANSI/ISO C++ International Standard has evolved over time, the
Standard C++ Library has not always kept up. Such is the case for the
times function object in the functional header file. In the standard,
times has been renamed to multiplies.
If you want to use multiplies in your code, to be compatible
with the ANSI/ISO C++ International Standard, use a conditional
compilation flag on the aCC command line.
For example, for the following program, compiles with the command line:
aCC -D__HPACC_USING_MULTIPLIES_IN_FUNCTIONAL test.c
// test.c
int times; //user defined variable
#include <functional>
// multiplies can be used in
int main() {}
// end of test.c
Depending on the existence of the conditional compilation flag,
functional defines either times, or multiplies, not both.
If you have old source that uses times in header functional
and a new source that uses multiplies, the sources cannot
be mixed. Mixing the two sources would constitute a non-conforming
program, and the old and new sources may or may not link.
If your code uses the old name times, and you want to
continue to use the now non-standard times function object,
you do not need to do anything to compile the old source.
Tools.h++ Library
The Tools.h++ Library is a foundation class library built on the
Standard C++ Library. Use its object oriented capabilities to
simplify coding and facilitate code reuseablility.
The Rogue Wave Software Tools.h++ Class Reference describes all
of the classes and functions in the Tools.h++ Library. It is
intended for use with Rogue Wave Standard C++ Library. It is
provided as HTML files. You can view these files with an HTML
browser by opening the file /opt/aCC/html/librwtool/ref.htm.
HP aC++ Runtime Support Library
The HP aC++ runtime support library is provided as a shared
library, /usr/lib/libCsup.so and as an archive library,
/usr/lib/libCsup.a.
The library supports the following functionality:
- Exception Handling
- Memory Management (operators new and delete)
- Start and termination of a C++ program
- Runtime type identification (type_info)
- Static object constructors and destructors
IOStream Library
The Standards-based IOstream capabilities of the Standard
C++ Library are still evolving. As a result, an HP C++ (cfront)
compatible IOStream library is provided in this release.
Linking to C++ Libraries
You can compile and link any C++ modules to one or more libraries.
HP aC++ automatically links the following with a C++ executable. Note
that when you specify the -b option to create a shared library, these
defaults do not apply.
- /usr/lib/hpux##/libCsup.so (the HP aC++ run-time support library)
- /usr/lib/hpux##/libstd.so (standard C++ library)
- /usr/lib/hpux##/libstream.so (iostream library)
- /usr/lib/hpux##/libc.so (the HP-UX system library)
- /usr/lib/hpux##/libdl.so (routines for managing shared libraries)
- /usr/lib/hpux##/libunwind.so (routines for unwinding)
- /usr/lib/hpux##/libm.so (math library)
(where ## is 32 or 64 - provided as part of the HP-UX core system)
Linking with Shared or Archive Libraries
If you want archive libraries instead of shared libraries, use the -a,
archive linker option. To create a completely archived executable, use the +A option.
To maintain compatibility on future releases, archive and shared libraries should not be mixed.
Refer to HP-UX Online Linker and Libraries User’s Guide for more information.
Specifying Other Libraries
You can specify other libraries using the -l option. For example, in order
to use the Tools.h++ library, specify -lrwtool:
aCC myapp.C -lrwtool
|
| Creating and Using Shared Libraries |
|
This section provides information about shared libraries that is specific
to HP aC++. It discusses the following topics:
Compiling for Shared Libraries
To create a C++ shared library, you must first compile your C++ source
with either the +z or +Z option. These options create object
files containing position-independent code (PIC).
Example:
aCC -c +z util.C
This example compiles util.C, generates position-independent
code, and puts the code into the object file util.o.
util.o can later be put into a shared library.
Creating a Shared Library
To create a shared library from one or more object files, use the -b option
at link time. (The object files must have been compiled with +z or
+Z.) The -b option creates a shared library rather than
an executable file.
Note: You must use the aCC command to create a C++
shared library. The aCC command ensures that any static
constructors and destructors in the shared library are executed at
the appropriate times.
Example:
aCC -b -o util.so util.o
This example links util.o and creates the shared library util.so.
Using a Shared Library
To use a shared library, you simply include the name of the library
on the aCC command line as you would with an archive library, or
use the -l option, as with other libraries.
The linker links the shared library to the executable file it creates.
Once you create an executable file that uses a shared library, you must
not move the shared library or the dynamic loader (dld.so)
will not be able to find it.
Note: You must use the aCC command to link any program
that uses a C++ shared library. This is because the aCC command
ensures that any static constructors and destructors in the shared
library are executed at the appropriate times.
Example:
aCC prog.C util.so
This example compiles prog.C, links it with the shared
library util.so, and creates the executable file a.out.
Example of Creating and Using a Shared Library
The following command compiles the two files Strings.C and Arrays.C
and creates the two object files Strings.o and Arrays.o.
These object files contain position-independent code (PIC):
aCC -c +z Strings.C Arrays.C
The following command builds a shared library named libshape.so
from the object files Strings.o and Arrays.o:
aCC -b -o libshape.so Strings.o Arrays.o
The following command compiles a program, draw_shapes.C, that
uses the shared library, libshape.so:
aCC draw_shapes.C libshape.so
Linking Archive or Shared Libraries
If both an archive version and shared version of a particular library
reside in the same directory, the linker links in the shared version
by default. You can override this behavior with the -a linker option.
Note: You can use the +A option if you are using only
archive libraries to create a completely archived executable.
The -a option tells the linker which type of library
to use. The -a option is positional and applies to
all subsequent libraries specified with the -l option until
the end of the command line or until the next -a option is
encountered. Pass the -a option to the linker with the -Wx,args option.
Syntax:
The syntax of the -a linker option when used with aCC is:
-Wl,-a,[archive | shared | shared_archive | archive_shared | default ]
| -Wl,-a,archive |
Select archive libraries. If the archive library does not
exist, the linker generates a warning message and does not create the output file. |
| -Wl,-a,shared |
Select shared libraries. If the shared library does not exist,
the linker generates a warning message and does not create the output file. |
| -Wl,-a,archive_shared |
If archive_shared is active, the archive form
is preferred, but the shared form is allowed. |
| -Wl,-a,shared_archive |
If shared_archive is active, the shared form
is preferred but the archive form is allowed. |
-Wl,-a,default |
Select the shared library if it exists; otherwise, select the archive library. |
Example:
The following example directs the linker to use the archive version
of the library libshape, followed by standard shared libraries
if they exist; otherwise select archive versions.
aCC box.o sphere.o -Wl,-a,archive -lshape -Wl,-a,default
Updating a Shared Library
The aCC command cannot replace or delete object modules in a
shared library. To update a C++ shared library, you must recreate the
library with all the object files you want the library to include.
If, for example, a module in an existing shared library requires a fix,
simply recompile the fixed module with the +z or +Z option,
then recreate the shared library with the -b option.
Programs that use this library will now be using the new versions of
the routines. That is, you do not have to relink any programs that use
this shared library because they are attached at run time.
|
| Advanced Shared Library Features |
This section explains the following additional features available to you with shared libraries:
Forcing the Export of Symbols in main
By default, the linker exports from a program only those symbols that were
imported by a shared library. For example, if an executable’s shared libraries
do not reference the program’s main routine, the linker does not include
the main symbol in the a.out file’s export list.
Normally, this is a problem only when a program explicitly calls
shared library management routines.
See Routines and Options to Manage C++ Shared Libraries.
To make the linker export all symbols from a program, use the -Wl,-E
option which passes the -E option to the linker.
Binding Times
Because shared library routines and data are not actually contained in
the a.out file, the dynamic loader must attach the routines and
data to the program at run time. To accelerate program startup time,
routines in a shared library are not bound until referenced. (Data
items are always bound at program startup.) This deferred binding
distributes the overhead of binding across the total execution time
of the program and is especially helpful for programs that contain
many references that are not likely to be executed.
Forcing Immediate Binding
You can force immediate binding, which forces all routines and
data to be bound at startup time. With immediate binding, the
overhead of binding occurs only at program startup time, rather
than across the program's execution. Immediate binding also
detects unresolved symbols at startup time, rather than during
program execution. Another use of immediate binding is to provide
better interactive performance, if you do not mind program startup
taking longer. To force immediate binding, use the
option -Wl,-B,immediate.
Example:
The following example forces immediate binding:
aCC -Wl,-B,immediate draw_shapes.o -lshape
To specify default binding, use -Wl,-B,deferred.
Refer to HP-UX Online Linker and Libraries User's Guide for more information.
Side Effects of C++ Shared Libraries
When you use a C++ shared library, all constructors and destructors of
non-local static objects in the library are executed. This differs
from a C++ archive library where only the constructors and destructors
that are actually used in the application are executed.
Routines and Options to Manage C++ Shared Libraries
You can call any of several routines to explicitly load and
unload shared libraries, and to obtain information about shared libraries.
If an error occurs when calling shared library management routines, the
system error variable, errno, is set to an appropriate error
value. Constants are defined for these error values in /usr/include/errno.h.
Thus, if a program checks for these values, it must include errno.h:
#include <errno.h>
Refer to errno(2) manpage for more information.
Linker Options to Manage Shared Libraries
Linker options are available for specifying shared library binding time,
symbol export, and other shared library management features.
Note: You must use the -W1,args compiler option to
specify any linker option on the compiler command line.
Refer HP-UX Online Linker and Libraries User's
Guide for more information about library management routines
and linker options.
Also refer shl_load(3X) and shl_unload(3X)
manpages.
|
| Standard HP-UX Libraries and Header Files |
|
Several libraries providing system services are included with HP-UX.
You can access HP-UX standard libraries by using header files that
declare interfaces to those libraries. These library routines
are documented in the HP-UX Reference Manual.
Location of Standard HP-UX Header Files:
The standard HP-UX header files are located in /usr/include.
Using Header Files:
To use a system library function, your HP aC++ source code must
include the preprocessor directive #include.
Example:
#include <filename.h>
filename.h is the name of the C++ header file for the
library function you want to use. By enclosing filename.h in
angle brackets, the HP aC++ compiler looks for that particular header
file in a standard location on the system.
The compiler first looks
for header files in /opt/aCC/include; if none are found, it
then searches /usr/include.
You can use header file options to modify the search path.
Example:
If you want to use the getenv function that is in the
standard system libraries (/usr/lib/hpux##/lib.so and
/usr/lib/libc.a), specify the following:
#include <stdlib.h>
(The external declaration of getenv is found in the header file /usr/include/stdlib.h.)
|
| Allocation Policies for Containers |
|
By default, allocating memory for STL containers is optimized for
large applications. Defaults have been tuned with speed efficiency
as a primary concern. Space efficiency was considered, but was
secondary. Therefore, memory is typically not allocated as required, because
this method is slow and inefficient. The containers obtain a block
of memory to hold many elements, and when this fills up, they get
another block. The size of the block depends on the element size.
As a result, containers with only a few items might end up
allocating too much memory. This default behavior can be adjusted to
individual application needs.
For -AP Standard Library
The inline template function __rw_allocation_size can be explicitly specialized to return the number of units for each type's use in any container:
template <>
inline size_t __rw-allocation_size(bar*,size_t) {
return 1;
}
This would initially allocate 1 unit when dealing with containers of type bar. Alternately, if RWSTD_STRICT_ANSI is not defined, then container member function allocation_size can be used to directly set buffer_size, the number of units to allocate.
For -AA Standard Library
The following 4 defines can change the container initial allocation and growth ratio:
For an arbitrary container type:
# define _RWSTD_MINIMUM_NEW_CAPACITY size_t(32)
# define _RWSTD_NEW_CAPACITY_RATIO float(1.618)
For a string type:
# define _RWSTD_MINIMUM_STRING_CAPACITY size_t(128)
# define _RWSTD_STRING_CAPACITY_RATIO float(1.618)
For more precise control of containers, the following explicit specialization can be used.
The namespace scope function __rw::__rw_new_capacity can be explicitly specialized to return the current size in elements of any container:
template <>
inline size_t __rw_new_capacity (size_t __size, const _Container*)
The parameters passed in are the current size in elements and the container's pointer. The default behavior results in an amortized constant time algorithm that dramatically increases rapidity while retaining a regard for space efficiency.
The defaults have been tuned with speed vs. space optimization of container performance with regard to allocation of memory.
The ratio parameter must be above 1 for an amortized constant time algorithm. Lowering the ratio will lower rapidity and improve space efficiency. This effect will be most noticable when working with containers of few elements (less than 32).
The following is a container allocation example for both the
-AP and -AA Standard library:
#include <list>
namespace std {} using namespace std;
#include <malloc.h>
#include <memory>
#define NUM 4
int printMallocInfo(const char*);
#ifndef DEFAULT
// specialize default size
// Default buffer size for containers.
#ifdef _HP_NAMESPACE_STD
namespace __rw {
template <>
inline size_t __rw_new_capacity(size_t __size, const list<int>*) {
printf("......\n");
// if small grow by 5, else by 1/8 current size
return __size < 100 ? 5 : __size / 8;
}
}
#else // -AP
template <>
inline size_t __rw_allocation_size(int*, size_t) {
printf("......\n");
return sizeof(int) >= 1024 ? 1 : 5;
}
#endif // -AA
#endif // DEFAULT
int main() {
int count = 0;
list<int> *tryit;
for (int i = 0;i<NUM;i++) {
printMallocInfo("about to create the list=======================");
tryit = new list<int>;
printMallocInfo("about to add an entry");
tryit->push_back(i);
printMallocInfo("1st entry added");
tryit->push_back(i + 1);
printMallocInfo("2nd entry added");
count++;
}
printMallocInfo("at end");
printf("%d\n", count);
}
int printMallocInfo(const char* title) {
static long lastValue;
struct mallinfo info;
info = mallinfo();
printf("%s\n",title);
printf("Memory allocation info:\n");
printf(" total space in arena = %d\n", info.arena);
#ifdef DETAILS
printf(" number of ordinary blocks = %d\n", info.ordblks);
printf(" number of small blocks = %d\n", info.smblks);
printf(" space in holding block headers = %d\n", info.hblkhd);
printf(" number of holding blocks = %d\n", info.hblks);
printf(" space in small blocks in use = %d\n", info.usmblks);
printf(" space in free small blocks = %d\n", info.fsmblks);
printf(" space in ordinary blocks in use = %d\n", info.uordblks);
printf(" space in free ordinary blocks = %d\n", info.fordblks);
printf(" keep option space penalty = %d\n", info.keepcost);
#else
printf(" space in use = %d\n",
info.usmblks + info.uordblks);
printf(" space free = %d\n",
info.fsmblks + info.fordblks);
#endif
//printf("\n\n size used is %d \n",( info.arena -lastValue )/NUM);
//lastValue = info.arena;
return 0;
}
|
| Migration Considerations when Using Libraries |
|
Refer to Migration Considerations when Using Libraries for more information.
|
|