ObjectStore Building C++ Interface Applications

Chapter 4

Compiling, Linking, and Debugging Programs

This chapter provides information about compiling, linking, and debugging your application.

The earlier topics address all platforms. The last three topics are each dedicated to a specific platform or group of platforms.

Using Standard Template Libraries

In the ObjectStore development environment, you use the schema generation utility ossg to create schema for the classes that need to be stored persistently. The front end of ossg is actually a C++ language parser. As input, it takes a source file that includes C++ header files, which in turn define the layout of the application objects. You must inform ossg which of those classes you want to mark so that you can create persistent instances of them at a later time.

ObjectStore can now be used to store STL objects persistently. There are a number of STL class library implementations available that can be used with ObjectStore. For example, ObjectSpace, Rogue Wave, and Visual C++ offer such implementations.

How to Store STL Types Persistently

In order to store STL types persistently, take the following steps:

  1. Include the STL header files as well as the ObjectStore headers in the schema source file, and then mark the STL types. See Creating Schema Source Files.

  2. Provide an STL allocator for persistent storage. The ObjectStore distribution does not include allocators, but does include an example that shows you how to create your own.

An example of an STL allocator using ObjectStore is also included in the directory $OS_ROOTDIR/examples/stl. Also see the discussion of standard template libraries in Persistent new and delete in Chapter 2, Persistence, of the ObjectStore C++ API User Guide.

Microsoft Visual C++ Restriction

ObjectStore Release 5.1 supports ObjectSpace STL, but does not yet support Visual C++ version 5.0 STL.

Moving an Application and Its Schema

The ossetasp utility patches an executable so that it looks for its application schema in a database that you specify.

Syntax

ossetasp -p  executable 
ossetasp  executable database
-p

Instructs ossetasp to display the pathname of the specified executable's application schema database. Do not specify database in the command line when you include -p.

executable

Specifies the pathname of an executable. On Windows systems, this can also be the pathname of a DLL.

database

Specifies the pathname of an application schema database. ObjectStore patches the specified executable so it uses this application schema.

Description

When the schema generator generates an application schema, ObjectStore stores the actual string given as the -asdb argument to ossg (or the -final_asdb argument, if specified). When the application starts, it uses that string to find the application schema database.

When you move or copy an ObjectStore application to a machine that is not running a Server, leave the application schema database on the Server host. Normally, the application schema database must be local to the Server.

After you copy or move an application to another machine, you must patch the executable so that it can find the application schema database. Run the ossetasp utility with the absolute pathname of the application schema database. Be sure to specify the name of the Server host.

A locator file allows a database and its application schema to be on a machine other than the Server host. See ObjectStore Management, Chapter 5, Using Locator Files to Set Up Server-Remote Databases.

Windows NT
On Windows NT systems, you can run the ossetasp utility on any executable or DLL that contains schema (that is, that has a schema object file produced by ossg linked into it).

Restrictions
This utility is available on all platforms except OS/2. On OS/2, as well as on all other platforms, you can use objectstore::get_application_schema_pathname(). See theObjectStore C++ API Reference, Chapter 2, Class Library, for details.

Working with Virtual Function Table (VTBL) Pointers and Discriminant Functions

There are two special cases in which ObjectStore needs to know, at run time, the locations of information in your application program's executable:

Vtbls
When you declare a class to have virtual functions or, in some cases, to have virtual base classes, it acquires an invisible data member, the virtual function table pointer. (Virtual function table is usually abbreviated as vtbl, pronounced veetable. On some platforms vtbls are called vfts for virtual function tables. Vtbl and vft indicate the same thing.) The vtbl points to a table of function pointers that the application uses to dispatch calls to virtual functions. The C++ compiler arranges for the correct function pointers to be placed in the virtual function table.

Persistent storage
When you persistently store an object belonging to a class with virtual functions, ObjectStore cannot store the vtbl pointer literally, since it is a pointer to the text or data segment of the current executable - a transient pointer. When the same program is run another time, or a different program opens the database, the vtbl might have a different location.

Discriminants
For some union types used persistently, ObjectStore requires that you provide an associated discriminant function, which indicates the field of the union currently in use. The function is used by the application at run time when a union is brought into virtual memory from persistent storage. (See Discriminant Functions in the ObjectStore Advanced C++ API User Guide for additional information about discriminant functions.) To handle a discriminated union, ObjectStore must know the address of the union discriminant function for the union. This is similar to the way that ObjectStore handles vtbls.

Relocation

When ObjectStore reads in an object with virtual functions, it supplies an appropriate vtbl pointer from the current application. This is called vtbl relocation.

When your application references a persistent object of a class with virtual functions, ObjectStore must fill in the vtbl pointer in the object. To fill in the vtbl pointer, ObjectStore must know the address of the vtbl for the class. Virtual function tables are not stored in databases; they are part of your executable.

During relocation, ObjectStore might need vtbls and discriminant functions. It finds them in tables that map class names to references to both vtbls and discriminant functions. The schema generator generates a C++ source file (or object file for Visual C++) containing these tables that relate your schema to your application.

These tables are filled in during application link or postlink or at program start-up time, or some combination of these, depending on the platform. At each of these steps, the referenced vtbls and discriminants are searched for in the executable and, if found, are entered into the tables. At run time, ObjectStore can use these tables to find items for relocation.

On cfront platforms, the os_postlink executable performs this job. On other platforms, the compiler does it. On some platforms, this search might be done at run time based on the currently available DLLs.

Missing VTBLs

Depending on your platform, missing vtbls can cause errors at compile time or at run time. It is better to find such errors at compile time. By default ossg reports these errors at compile time. An optional ossg flag, -weak_symbols, can be used to suppress the default behavior. See Chapter 3, Generating Schemas, for detailed information about ossg syntax.

Symbols Missing When Linking ObjectStore Applications

Sometimes when linking, particularly with optimizations enabled, you are told that various symbols required by the application schema object file are missing. These symbols on non-Windows platforms (including OS/2) begin with __vtbl or __vft, or end with __vtbl. On Windows the symbols begin with ??_7. This happens because ObjectStore needs access to the virtual function tables (vfts) for some classes, and the C++ compiler does not recognize these tables as being needed. The easiest way to get these symbols is to add a nonstatic dummy function such as the following

void foo_force_vfts(void*){
      force_vfts(new A);
      foo_force_vfts(new B);
...
}
Creating instances of a class causes the class's vfts, as well as those of bases that have out-of-line default constructors, to be created in this file.

Abstract classes
If one of your classes is abstract, a variant of the above approach is needed, since you cannot allocate an abstract class. You can provide an out-of-line constructor for the class, or you can allocate a nonabstract derived class in such a way that inline constructors are used for the abstract class. For example, if the original class definitions were

class A {
      virtual void foo() = 0;
};
class B : public A {
       virtual void foo();
};
then class A might be missing its vft. However, an unoptimized new B would call A's inline default constructor, which would reference the vft for A. But if class B had an out-of-line constructor, this would not work. Then it would be easiest to make an out-of-line constructor for A:

class A {
      virtual void foo() = 0;
      A(){}
      friend void force_vfts(void*);
      A(void*);
};
class B : public A {
      virtual void foo();
};
and define A::A(void*){} in some file.

Instantiating collection classes
If you are using a parameterized collection class, you must instantiate the other collection classes because they have casts to each other. A work around is to declare this and link it. For example:

void foo_force_vfts(void*) {
      foo_force_vfts(new os_Set< missing-type>);
      foo_force_vfts(new os_List< missing-type>);
      foo_force_vfts(new os_Array< missing-type>);
      foo_force_vfts(new os_Bag< missing-type>);
      foo_force_vfts(new os_Collection< missing-type>);
}
There are additional considerations for building applications that use collections. See Instantiation Problem with Template Collection Classes.

Run-Time Errors from Missing VTBLs

On some platforms (without weak symbol support), you find out about the missing vtbls at link time. The vtbls are marked in the schema output file, but are not marked in the application. This is frequently the case for parameterized collections classes (os_Set, os_List, and so on).

Sometimes an executable does not have vtbls for all classes with virtual functions in the schema. When a vtbl pointer for a class is not available, ObjectStore fills in the vtbl pointer for the class's instance with a special vtbl that signals an error when any of the virtual functions is called.

No constructor
Missing vtbls can occur when your application calls a virtual function on an instance of a class for which no constructor call appears in the source. Since a call to the class's constructor does not appear in the source, the linker does not recognize the class as being used and does not link in its implementation. But an ObjectStore application can use a class whose constructor it never calls by reading an instance of the class from a database. To avoid this situation, put a call to the class's constructor inside a dummy function that is never called.

Class not in schema
Missing vtbls can also occur when the class is not included in the application's schema, either because its definition was not included in the source or because the class was only reachable from explicitly marked classes by means of void* pointers. In this case, the solution is to include a definition of the class, or explicitly mark it with OS_MARK_SCHEMA_TYPE().

Inline virtual functions when using noncfront compilers
Noncfront compilers include C Set ++, DEC C++, SGI C++, Sun C++, VisualAge C++, and Visual C++.

When you are using a noncfront compiler (except on OS/2), if all virtual functions of a class are inline, either because they are defined fully in the class specification or with the inline keyword, the compiler treats the virtual function table as static. Because the virtual function table is viewed as static, the vtbl pointers for such a class are not available (that is, not seen globally, therefore not available to ObjectStore) because the locations of the virtual functions were not filled in by ossg.

The solution to this problem is to put an out-of-line virtual function in each class with a missing vtbl. You can either modify an inline function or you can add a trivial noninline function. To determine which classes need an out-of-line virtual function, you can run ossg with the -no_weak_symbols option. This identifies missing vtbls at link time rather than at run time. For information about this option, see page 43.

A class that meets the following conditions might also need the addition of a noninline virtual function:

This is because the vtbl from the base class might become invalid as a result of the derivation.

Visual C++
When you are using Visual C++, an alternative solution is to export a class that has only inline virtual functions.

OS/2
On OS/2, correct vtbls are available for classes that have only inline virtual functions because you run ossg with the -cd option.

-rtdp option
Missing vtbls can also occur depending on what you specify for the -rtdp option when you generate the schema.

To obtain a list of missing vtbls at run time, set the OS_TRACE_MISSING_VTBLS environment parameter. See ObjectStore Management, OS_TRACE_MISSING_VTBLS.

AIX C Set ++ - Virtual Function Table Pointers

When the ObjectStore client reads a page from the Server into your application, it must store correct virtual function table pointers to those objects that have virtual function tables (vfts). To do this, the client must have the addresses of the vfts for the classes in your schema.

ObjectStore derives these addresses as part of schema generation. The application schema source file generated by ossg contains extern declarations of the vft symbols. The schema generator stores their addresses in a table when your program starts execution.

Normally, vfts are declared extern in all modules that reference them except in the module that defines the first noninline virtual function. That module defines the vft as a global symbol.

However, there are several cases in which there is no module that corresponds to the first noninline virtual function. For example, all the class's virtual functions can be inline. In these cases, C Set ++ generates a static vft in each module that allocates an object of the class. In such a case, the application schema source file cannot link to the vft, since it is static in some other module or modules.

You can tell if you have such classes with the -qinfo:vft argument to C Set ++. If it informs you of any classes with static links, and if you want to store them persistently, you must either add an out-of-line virtual function to each such class, or use the command-line arguments that control vft allocation to make the vfts accessible. Aside from making ObjectStore work, it makes your executable smaller. Here is an example of -qinfo:vft output:

class A {
public:
      virtual foo():
      int a;
      A() {a=0;}
};
class B : public virtual A {
public:
      virtual foo();
      int b;
      B() {b=1;}
};
class C : public B {
      int c;
      C() {c=2;}
};
int B::foo() {}
xlC_r -qinfo=vft -c x.C
"x.C", line 29.1: 1540-017: (W) Return value of type "int" is expected.
"x.C", line 1.1: 1540-281: (I) The virtual function table for "A" will be 
defined where "A::foo()
"x.C", line 10.1: 1540-280: (I) The virtual function table for "B" is defined 
with "extern" links.
"x.C", line 20.1: 1540-280: (I) The virtual function table for "C" is defined 
with "extern" links.
The two C Set ++ arguments are -qvftable and -qnovftable. -qvftable instructs C Set ++ to allocate global vfts for all classes visible in the compilation unit. -qnovftable forces all vfts to be referenced externally.

The simplest way to make C Set ++ work with ObjectStore is to create an additional source file that includes the definitions for classes that have static links. Compile it with -qvftable, and link it. This does not avoid the extra static copies of the table in any modules that allocate objects of this class, but it does allow the application schema source file to link to them.

To avoid extra copies, you have to compile all ordinary sources with -qnovftable, and then add -qvftable to the appropriate sources so that each vft is defined exactly one time.

Using new and delete Operators with cfront

A design limitation of the C++ language fails to match overloadability of the new operator with a corresponding overloadability of the delete operator. Therefore, to make deletion of persistent objects work transparently, ObjectStore must take control of some of the internals of the C++ storage allocation run-time environment, including _ _vec_delete.

Note that there is still a limitation that ObjectStore cannot completely address - if a shared library that is not itself linked with the ObjectStore library uses C++ allocation, it will not share the copy of _new_handler provided by ObjectStore.

Debugging Applications

In addition to native debuggers, alternatives for debugging applications include

See ObjectStore Management, Chapter 3, OS_TRACE_MISSING_VTBLS.

If you use schema protection, you can remove all symbol names from your application so that use of a debugger does not display the names of functions on the stack. This makes it harder for someone to subvert schema protection by analyzing information provided by the debugger.

Dependency of Object Files on Header Files

You should maintain complete dependencies of object files on header files. Object Design recommends automating this by using a dependency generation tool in your makefiles.

In previous releases on some platforms, ObjectStore provided the osmakedep command. This is no longer the case. Your compiler vendor should supply you with a configuration management tool.

Retrofitting Makefiles

When you use a makefile to build an ObjectStore application, if you start with a makefile that you use for another application, be sure to follow the instructions in this book for specifying libraries. ObjectStore brings in certain system libraries that are not explicitly specified.

If you copy an on-line version of an ObjectStore makefile from ObjectStore documentation sources, make sure that you have tabs at the beginning of appropriate lines and not spaces.

UNIX

This section provides information for compiling and linking ObjectStore applications on UNIX platforms. Unless a particular UNIX platform is named in the heading, the material refers to all UNIX platforms that support ObjectStore C++ interface Release 5.1.

Linking with ObjectStore Libraries

ObjectStore includes libraries that you must link with when you build your application. Libraries allow multiple programs to share code without redundantly compiling the source. Applications use libraries by specifying them at link time.

Requirement
You always link with the libos library. If you are using full ObjectStore, you use $OS_ROOTDIR/lib/libos; if you are using ObjectStore/Single, you use $OS_ROOTDIR/libsngl/libos.

You must also link with either the libosthr or libosths libraries. You must link with additional ObjectStore libraries according to the features you use in your code, as shown in the following table. If there is more than one library, you must specify them in the order given. See Examples of Passing Libraries to the Linker.
If Your Application Uses This FeatureLink with These Libraries in This Order
Any ObjectStore feature

libos {libosthr or libosths}

Collections

liboscol libos {libosthr or libosths}

Compactor

liboscmp libos {libosthr or libosths}

Database utilities:



liboscol libosmop libostcl libosdbu libos {libosthr or libosths}

libosdbu libos {libosthr or libosths}

MOP

libosmop liboscol libos {libosthr or libosths}

Queries and indexes

libosqry liboscol libos {libosthr or libosths}

Relationships

liboscol libos {libosthr or libosths}

Schema evolution

libosse libosqry liboscol libos {libosthr or libosths}

C run-time library

libos {libosthr or libosths}

Threads library
The libosthr or libosths library is for threads. Be sure to use the correct threads library for your platform:
PlatformThreads Library
AIX

libosthr

Digital UNIX

libosthr

HP-UX

libosthr or libosths

IRIX

libosths

Solaris 2

libosthr or libosths

If you have a real threads package, link with the libosthr library. The libosths library is a stub threads library.

IRIX shared process (sproc) restrictions
Use pthreads but not sprocs in ObjectStore Release 5 and later. ObjectStore 5.0 for IRIX does not support concurrent ObjectStore operations (for example, transactions) in more than one process in a shared process group, where the processes are sharing virtual memory. If you want your program to use ObjectStore 5.0, it is best to restrict all ObjectStore operations to a single process in the shared process group. If you want ObjectStore operations in a number of the processes, the program must minimally ensure that

C++ run-time library
You must link libos before the C++ run-time library (often called libC). On some platforms it is possible for the order to come out wrong when you link with shared libraries that use shared libraries. Linking with libos first prevents this problem.

Specifying libraries
Use the -l (lowercase l as in link) option to pass library names to the linker. When you specify an ObjectStore library, do not include the lib portion of the library name. For example:

CC -L$(OS_ROOTDIR)/lib -o my_exec main.o os_schema.o foo.o 
-los
Note that the -L$(OS_ROOTDIR)/lib option begins with an uppercase L as in Library.

Exclusive libraries
You cannot link with both libosse and liboscmp.

HP-UX and DCE
This release of ObjectStore works with HP-UX 10. DCE, bundled with HP-UX 10, provides thread support on HP-UX. If you use threads and link with DCE, you must use libosthr instead of libosths.

When using threads (libosthr), while ObjectStore is running in its fault handler, DCE masks most signals. Therefore, when DCE is linked into an ObjectStore application, ObjectStore's fault handler reenables the following signals:

If an application wants to reenable a different set of signals, this default behavior can be overridden using the following interfaces:

extern "C" void _ODI_set_reenable_mask(unsigned int new_mask);
extern "C" unsigned int _ODI_get_reenable_mask();
Consult Object Design Technical Support before using these interfaces.

The mask is a bit vector of the signal values. A value of 1 indicates that the corresponding signal is enabled when ObjectStore's fault handler is entered.

Note that _ODI_get_reenable_mask returns 0 if _ODI_set_reenable_mask has not been called.

Also note that regardless of the reenable_mask value, ObjectStore always reenables the signal being handled (SIGSEGV or SIGBUS).

Examples of Passing Libraries to the Linker

When building an application that uses compaction, MOP, queries, and collections, specify ObjectStore libraries like this:

-loscmp -losmop -losqry -loscol -los {-losthr | losths}
When building an application that uses the schema evolution feature, specify libraries like this:

-losse -losqry -loscol -los {-losthr | losths}
When building an application that uses database utilities, specify the libraries like this:

-losdbu -los {-losthr | losths}
If you need all ObjectStore libraries and you need a stub threads library because you do not have real threads, link with the libraries in this order:

{-losse | -loscmp} -losmop -losqry -loscol -los -losdbu -losu -losths
If you need all ObjectStore libraries and you have a real threads package, link with the libraries in this order:

{-losse | -loscmp} -losmop -losqry -loscol -los -losdbu -losu -losthr 

DEC C++ 64-Bit Pointer Considerations

Since the Digital UNIX operating system environment supports 64-bit pointers, using this compiler with ObjectStore presents unique decisions for application writers. Fortunately, ObjectStore Release 5.1 and the DEC C++ 5.1 compiler include options that offer alternatives depending on your particular application needs.

Usually, DEC C++ uses 64 bits for all pointers in generated code. The eXtended Truncated Address Support Option (xtaso), and other #pragma directives and compiler options, let code with 32-bit pointers coexist within this 64-bit operating system environment. If you use only -xtaso, and have 64-bit pointers in the objects stored in your database, then your database will not be heterogeneous.

Note that within a compilation unit, pragma statements allow the user to switch between 32-bit and 64-bit classes selectively. However, ossg deals with these pragma statements at the granularity of a complete top-level class.

Software version requirements
You must be running Digital UNIX version 4.0A and the DEC C++ compiler version 5.5-005 general release to take advantage of the ObjectStore 5.0 and DEC 5.5 compiler features described here. You should also install the DEC patch OSF360-350222. This patch includes the previously required 350108 patch.

If you are uncertain what versions of software are running on your system, check them with the following commands.

To determine the operating system version, enter

uname -a
The response should be of the form

V3.2 148 
where 148 corresponds to 3.2.C.

To determine the version of the compiler, enter

cxx -V | tail -1
The result should be of the form

DEC C++ V5.1-1 
for DEC OSF/1 (Alpha) or greater.

How to use the -xtaso option
Use of -xtaso options, pragma statements, and the -taso linker option allows application programs that make intensive use of memory to make efficient use of operating system resources. It allows for the manipulation of objects containing 32-bit pointers. This also enables the use of libraries, such as the ObjectStore libraries, that were built using 32-bit pointers. ObjectStore libraries were built in this manner to support heterogeneous access to databases between this platform and those that do not support 64-bit pointers. In order to use both 64-bit and 32-bit pointers compatibly, it is necessary to limit the application to a 31-bit virtual address space. It is important to select one of these -taso options when using ObjectStore even if you want 64-bit pointers to be the default, because you need to ensure that your ObjectStore application uses 31-bit virtual address space. If you do not specify the -taso option, this is not the case.

This means that when you write ObjectStore applications, you need to use some of the methods described in this section to accommodate 32- and 64-bit pointers. Specifically, the considerations you must address are

The sections that follow describe techniques and methods you should use to avoid compilation errors that might result from mixing 32- and 64-bit pointers.

Compiler options and pointer size directives
To use 32-bit pointers, you can use command-line compiler options and/or #pragma preprocessor directives. For example, ObjectStore's collections are implemented with 32-bit pointers to support heterogeneous access. Therefore, you need to use these options to ensure correct conversion between 64- and 32-bit pointers.

The pointer size compiler options are -xtaso, -xtaso_short, -vptr_size, and -vptr_size_short. You can accommodate 32- and 64-bit code using the -xtaso and -vptr_size or -xtaso_short and -vptr_size_short compiler options. The following table describes the compiler options:
Compiler OptionDescription
-xtaso

Sets the default pointer size of the compilation unit to 64 bits (for all pointers except virtual function and virtual base pointers in a C++ class object). This is the normal default unless overridden by -xtaso_short.

-xtaso_short

Sets the default pointer size of the compilation unit to 32 bits (for all pointers except virtual function and virtual base pointers in a C++ class object).

-vptr_size

Makes 64 bits the default size of virtual function and virtual base pointers in a C++ class object. This is the default unless overridden by -vptr_size_short.

-vptr_size_short

Makes 32 bits the default size of virtual function and virtual base pointers in a C++ class object.

Whenever any of these options is specified on the command line, the following actions occur:

When using #pragma directives to control pointer size, and these compiler options, you must ensure that the pointer size of any particular pointer is used consistently across compilation units. This is especially true when you call functions in any library compiled with different pointer sizes. The #pragma directives are defined below.

To use ObjectStore with the DEC C++ compiler, you must select one of the following methods of protecting pointer size assumptions:

Considerations in deciding which of these approaches is the most suitable for your application are the relative importance of heterogeneity and whether disk space is an issue. (64-bit executables and libraries use considerably more disk space than 32-bit executables and libraries.)

If heterogeneity is not a consideration for your application and you are not concerned with the amount of memory used for 64-bit pointers, you can take advantage of the 64-bit operating system environment and compile using the -xtaso option. This option makes 64 bits the default pointer size and uses 32-bit pointers for particular declarations. In such a case, it is possible to use third-party class libraries that only support 64-bit pointers. See "Using the -xtaso option" for details about using this option.

If heterogeneity is an important consideration for your application, you can easily take advantage of ObjectStore's 32-bit pointers in this 64-bit operating system environment by compiling with the -xtaso_short option. This option makes 32 bits the default pointer size and uses 64-bit pointers for particular declarations. The 32-bit pointer data type allows you to minimize the amount of memory used by dynamically allocated pointers, and assists in porting applications that contain assumptions about pointer sizes. See "Using the -xtaso option" for details about this option.

#pragma pointer_size directive
The #pragma pointer_size directive controls pointer size allocation for the following:

ossg reminder
Remember that ossg deals with these pragma statements at the granularity of a complete top-level class. This consideration also applies to embedded members and inherited base classes.

For this pragma statement to have any effect, specify -xtaso, -xtaso_short, -vptr_size, or -vptr_size_short on the cxx command.
#Pragma DirectiveDescription
pointer_size

Controls the pointer size of all pointers except virtual function and virtual base pointers in a C++ class object.

Has an effect only if you specify one or more of the pointer-size compiler options.

required_pointer_size

Has the same effect as #pragma pointer_size but is always enabled, whether or not you specify any pointer-size compiler options.

required_vptr_size

Controls the size of virtual function and virtual base pointers in a C++ class object.

Always enabled, whether or not you specify any pointer size compiler options.

This pragma statement has the following syntax:

      #pragma pointer_size {long|64}
      #pragma pointer_size {short|32}
      #pragma pointer_size restore
      #pragma pointer_size save
The #pragma syntax options are defined in the following table.
OptionDescription
long or 64

Sets as 64 bits all pointer sizes in declarations that follow this directive until the compiler encounters another #pragma pointer_size directive.

short or 32

Sets as 32 bits all pointer sizes in declarations that follow this directive until the compiler encounters another #pragma pointer_size directive.

restore

Restores the saved pointer size.

save

Saves the current pointer size onto a pushdown stack.

The save and restore options are particularly useful for specifying mixed pointer support and for protecting header files that interface to older objects. Objects compiled with multiple pointer size pragma statements are not compatible with old object files, and the compiler cannot detect that incompatible objects are being combined.

Using the -xtaso option
The -xtaso compiler option is useful when heterogeneity is not a consideration. Using -xtaso enables you to use the 32-bit pointer size only for selected pointers. The -vptr_size option makes 64 bits the default size of virtual function and virtual base pointers in a C++ class object (64 bits is the normal default). This -xtaso option also enables #pragma pointer_size and passes -taso to the linker.

With this approach, most pointers in your application are 64 bits, and 32 bits are used for selected pointers. To use this method, compile with -xtaso to enable #pragma pointer_size and cause the cxx command to pass -taso to the linker. In addition, use #pragma pointer_size, #pragma required_pointer_size, and #pragma required_vptr_size to control the pointer sizes for particular declarations. For example, to save space in an object, declare a class as follows:

#pragma pointer_size save
#pragma required_vptr_size save
#pragma pointer_size short
#pragma required_vptr_size long
            class Table_Node {
                  char *table;    // 32 bit pointers
                  Table_Node *next;
                  Table_Node *(Table_Node::*search)(char *);
                              // pointer to member has
                              // 2 32 bit fields
            public:
                  void insert_node(char *);
                  Table_Node *extract_node(char *);
                  Table_Node *search_forward(char *);
                  Table_Node *search_backward(char *);
            };
#pragma pointer_size restore
#pragma required_vptr_size restore
When you use this approach, it is important to specify the pointer size #pragma directives after any #include directives so the header files that assume 64-bit pointer sizes are not affected.

Using typedefs
In order to provide an interface to an application using 64-bit pointers and the ObjectStore library, which uses 32-bit pointers, a number of new typedefs are available.

Use typedefs when building an application using the -xtaso option to avoid compilation errors that result from incompatible interface definitions. The following code example produces such a compilation error:

#include <ostore/ostore.hh>
int main(int, char **)
{
      os_int32 max_servers;
      os_server **servers;
      os_int32 n_servers;
      objectstore::get_all_servers(max_servers, servers, n_servers);
}
$ cxx example.cc -c -xtaso
The error message that results might look as follows:

example.cc:9: error: In this statement, the referenced type of the pointer 
value "servers" is "long pointer to os_server", which is not compatible with 
"short pointer to os_server".
Compilation terminated with errors.
The use of the typedefs enables the compiler to perform the correct pointer conversions to interface to the ObjectStore libraries. More precisely, the typedefs listed on the next page solve the situation of a compound pointer, that is, a pointer-to-a-pointer, which cannot be automatically converted by the compiler. The compiler automatically converts the pointer-to but does not convert what it points to, the a-pointer part.

An example of such a typedef is os_server_p. It is defined as an os_server*.

If you modify the example, replacing os_server **servers with os_server_p *servers, the program compiles cleanly:

#include <ostore/ostore.hh>
int main(int, char **)
{
      os_int32 max_servers;
      os_server_p *servers;
      os_int32 n_servers;
      objectstore::get_all_servers(max_servers, servers, n_servers);
}
$ cxx example.cc -c -xtaso 
Note that this affects C++ references as well as pointers.

The comprehensive list of typedefs supplied by the ObjectStore header files follows
typedef char const* os_char_const_p;

typedef char* os_char_p;

typedef objectstore_exception& objectstore_exception_r;

typedef os_bound_query const& os_bound_query_const_r;

typedef os_canonical_ptom& os_canonical_ptom_r;

typedef os_coll_query& os_coll_query_r;

typedef os_coll_rep_descriptor const& os_coll_rep_descriptor_const_r;

typedef os_coll_rep_descriptor const* os_coll_rep_descriptor_const_p;

typedef os_collection const& os_collection_const_r;

typedef os_collection* os_collection_p;

typedef os_cursor const& os_cursor_const_r;

typedef os_database_root& os_database_root_r;

typedef os_int32& os_int32_r;

typedef os_old_reference& os_old_reference_r;

typedef os_old_reference_version& os_old_reference_version_r;

typedef os_rawfs_entry* os_rawfs_entry_p;

typedef os_reference& os_reference_r;

typedef os_reference_local& os_reference_local_r;

typedef os_reference_version& os_reference_version_r;

typedef os_transaction const* os_transaction_const_p;

typedef os_typed_pointer_void const& os_typed_pointer_void_const_r;

typedef tix_exception* tix_exception_p;

typedef void const* os_void_const_p;

typedef void const*& os_void_const_p_r;

typedef void* os_void_p;

typedef void*& os_void_p_r;

.

Using the -xtaso_short option
The -xtaso_short option makes 32 bits the default pointer size. In this mode you need to use some mechanism to accommodate code that expects 64-bit pointers. If you select this method, remember that references to other libraries can be more complicated since any library with compound pointers requires you to use #pragmas.

To use this option, compile with the -xtaso_short and -vptr_size_short options on the cxx command. The -vptr_size_ short option makes 32 bits the default size of virtual function and virtual base pointers in a C++ class object. The -vptr_size_ short option also enables #pragma pointer_size and passes -taso to the linker.

It is important to protect header files so that when the header file is included in a compilation (using #include), the pointer size assumptions are the same as those made when the code associated with the header files was compiled.

#pragmas and function declarations
In the default C++ installation, none of the system header files, including those for the standard C library, is protected, but see "Using the header file protection option" for an automated method of providing this protection. The alternative methods for doing this are to

If you include a system-defined function declaration with pointers in its signature - without including it from a protected header file - you need to protect it with a #pragma pointer_size directive.

#pragma pointer_size save
#pragma pointer_size long
extern "C" {
int getrusage (
      int who,
      struct rusage *r_usage );
}
#pragma pointer_size restore
Modifying each header file
To modify each header file, use the #pragma environment directive as shown:

#pragma __environment save              // Save pointer size
#pragma __environment header_defaults   // set to system defaults
// existing header file
#pragma__environment restore // Restore pointer size
Using the header file protection option
With the header file protection option, you can place special header files in a directory. DEC C++ processes these special header files before and after each file included with the #include directive. These special header files are named

The compiler checks for files with these special names when processing #include directives. If the special prologue file exists in the same directory as a file with the #include directive, the contents of the prologue file are processed just before the file included with the #include directive. Similarly, if the epilogue file exists in the same directory as the file included with the #include directive, it is processed just after that file.

For example, if the source code has #include <stdio.h>, the order of file processing would be

  1. /usr/include/__DECC_include_prologue.h

  2. /usr/include/stdio.h

  3. /usr/include/__DECC_include_epilogue.h

  4. Whatever follows #include <stdio.h>

For convenience, you can protect header files using the script

/usr/lib/cmplrs/cxx/protect_system_headers.sh
This script creates, in all directories in a directory tree that contain header files, symbolic links to special header prologue and epilogue files.

The default directory tree root assumed by the script is /usr/include, but you can specify other roots.

Embedded ObjectStore members
All ObjectStore libraries use 32-bit pointers to support heterogeneous access, and therefore must be used in 32-bit mode. This means that the ObjectStore headers are protected so that 32 bits is the default pointer size. Any time an ObjectStore-defined object is embedded in an application object, that class - or at least the collection declaration - must be protected as well. This occurs most commonly in the collection class library, but it also applies to other ObjectStore classes such as os_Reference. Also note that any ObjectStore relationship is an embedded collection.

Troubleshooting Errors

When you are working in a mixed 32- and 64-bit environment, there are a variety of conditions that can cause errors. Several error message samples and the conditions that caused them are described below. You might see such errors if you have combined -xtaso and -xtaso_short incorrectly, or failed to specify the -taso option to the linker.

      No handler for exception:
      Miscellaneous ObjectStore error
      An inconsistency was detected during the allocation of an object of 
      type part. The compiler believes the allocation size should be 40 bytes,
      while the schema believes it should be 32 bytes. Verify that the 
      arguments to `new' match the type and/or array count of the object
      being allocated.
      (err_misc)
      Abort process (core dumped)
      ossg -assf osschema.cc -asdb coll.adb   -I/usr/local/ostore/4.0.0.C/
      include schema.cc /usr/local/ostore/4.0.0.C/lib/liboscol.ldb
      <err-0004-0008>
      The following class definitions in library schema "/usr/local/
      ostore/4.0.0.C/lib/liboscol.ldb" 
      were inconsistent with the corresponding definitions obtained from 
      other library or compilation schemas specified for building the 
      application schema:
      "os_set" from the schema source file "/usr/local/ostore/4.0.0.C/
      include/ostore/coll/coll_int.hh"
      the class size changed from 24 to 40
      "os_tinyarray" from the schema source file "/usr/local/
      ostore/4.0.0.C/include/ostore/coll/query.hh"...
      *** Exit 1
      Stop.

HP Requires Linker Options

You must supply -Wl (this is a lowercase l), -E to cc or CC. This option is necessary so that symbols are exported correctly. If this is not done, virtual function table pointers (vtbls) are not available when ObjectStore relocation occurs. For this reason, your application might run correctly the first time, but signal an exception when run the second time. The exception would be

No handler for exception:
Attempt to call virtual function without vtbl.
Vtbl for type os_packed_list not linked into application. (err_missing_vtbl)
IOT trap (core dumped)
Here is an example of an HP makefile link command line:

$(CCC) +eh -Wl,-E -g -o test test.o os_schema.o $(LDLIBS)

+eh Mode Supported

ObjectStore only supports +eh mode of HP CC in Release 5.1.

HP aC++ Source Files

HP recommends that you name HP aC++ source files with an extension of either .c or .C. possibly followed by additional characters. This applies to schema source files as well because they are preprocessed for ossg using aCC.

Note that HP recommends that you use extensions consisting only of .c or .C without additional characters, because while the compiler accepts the additional characters, other HP tools and environments might not.

If you compile only, each C++ source file produces an object file whose prefix is identical to the source file but with a .o suffix. However, if you compile and link a single source file into an executable program in one step, the .o file is automatically deleted.

HP C++ Compiler Messages

When using the HP C++ compiler, you might receive the messages below when building your application. Although the application seems to run correctly, removing the -g option from the compilation and link phases resolves the errors. You might see these messages during the compilation phase:

CC: "myprog.C", line 82: warning: debug.object_ids: weird 
vtable->vclass for os_Collection <const MyObject*> (198)
CC: "myprog.C", line 8: warning: debug.emit_variable: bad address found
for name ABC::xyz::ex (251)
Also, you might see these warnings during the link phase:

pxdb: [cu: 0 index: 0x136] can't link template/expansion
pxdb: [cu: 0 index: 0x14f] can't link template/expansion
pxdb: [cu: 0 index: 0x168] can't link template/expansion
pxdb: [cu: 0 index: 0x181] can't link template/expansion
You might see the following warnings during compilation of a source file that uses stack transactions (that is, that contains OS_BEGIN_TXN/OS_END_TXN macros):

CC: "myprog.cc", line 342: warning: label in block with destructors (2048)
Such warnings, where they concern the stack transaction macros, can safely be ignored.

SGI IRIX Compiler Option

On SGI IRIX 6.2 you must use the -n32 option to the compiler. The
-32 and -64 options are not currently supported.

Sun C++ Compiler Options

Sun C++ 4.0 has a compile-time option, -pto, that creates all template instantiations in the current object file. Do not use this option when developing ObjectStore applications, because it makes everything (including vtbls) static. Since the vtbls are static, ObjectStore cannot get at them and gets the wrong vtbl, which leads to an error.

-vdelx compiler option
When you are using SPARC ProCompiler C++, you must always specify the -vdelx compiler option. The -vdelx option to CC generates the correct calling sequence for persistent vector deletes. For example:

delete [] persistent_array;
Without -vdelx, the compiler generates a direct call to the Sun vector delete routine. This routine returns an error message indicating that it did not allocate the array:

error: delete [] does not correspond to any \Qnew'
If you use CC to link (by means of ld), then the linker receives the correct libraries. Be sure to study the CC and ld man pages for details, especially if you invoke ld directly.

On Solaris 2.x systems, you must compile (and link) ObjectStore applications with real thread support. Specify -losthr on the link line to supply the proper library for real thread support. The libosths library, a stub threads library, can also be used with Solaris 2.x systems. Using this library can result in higher performance in some circumstances because it turns off thread locking.

Debugging with DBX
To use the multithread-related (MT) commands of DBX to debug a multithreaded application, you need to obtain a separate license from Sun. However, you are not required to use a special version of DBX. MT features are part of the standard DBX. You can debug without the multithreaded debugging commands. The DBX debugger reports an error if you do not have threading licenses, but nonetheless it debugs single-threaded applications.

Solaris 2 Linking

ObjectStore supports linking with and without threads. This means there are two ObjectStore thread support libraries on Solaris 2 - libosths and libosthr.

Here is an example of the same program (foo) compiled and linked in both configurations.

On Solaris 2.x, you must always specify the -mt compiler option on the CC command line. This is required for a successful compilation.

Linking with threads
With threads:

CC -mt -I$(OS_ROOTDIR)/include $(CCFLAGS) -o foo 
            -L$(OS_ROOTDIR)/lib -los -losthr 
Note that to link an application to use threads,

Linking without threads
Without threads:

CC -I$(OS_ROOTDIR)/include $(CCFLAGS) -o foo 
            -L$(OS_ROOTDIR)/lib -los -losths
Note that to link an application that does not use threads,

Sample Makefile Template

The makefile on the next page is a template for building ObjectStore applications. This makefile is for an application that uses queries and collections.

In an ObjectStore makefile, in the LDLIBS line, you must specify each library with which you are linking.

Then, in the line of the makefile where ossg generates the application schema, you must specify the library schemas needed by your application schema. For each library schema that you specify in the ossg command line, you must specify the corresponding library in the LDLIBS line.

Note that the reverse is not true. For each library that you specify in the LDLIBS line, you do not necessarily specify a library schema in the ossg command line. This is because every library does not necessarily have a library schema. Only those libraries that store or retrieve persistent data have associated library schemas.

OS_POSTLINK and os_postlink
OS_POSTLINK is a macro provided with ObjectStore. It calls the os_postlink command that fixes vtbls and discriminants in the executable, if needed. While os_postlink does not actually do anything on some platforms, Object Design recommends that you always include it so that its absence does not cause a problem if you move the application to another platform. For more information about os_postlink, see Working with Virtual Function Table (VTBL) Pointers and Discriminant Functions.

Tabs and spaces
If you are using an on-line version of this book, and you copy a makefile and try to use it, make sure that there are tabs and not spaces at the beginning of relevant lines.

Application schema database
In makefiles, you should not specify an existing ObjectStore database as the application schema database. Doing so can corrupt your build process if the Server log has not been propagated to the database.

Makefile template
include $(OS_ROOTDIR)/etc/ostore.lib.mk
APPLICATION_SCHEMA_PATH= app-schema-db 
LDLIBS = $(OS_EXPORT) -losqry -loscol -los -losths [ other libraries]
SOURCES = .cc  files 
OBJECTS = .o  files 
EXECUTABLES =  executables 
CCC=CC 
all: ${EXECUTABLES}
executable: $(OBJECTS) os_schema.o
      $(CCC) -o executable $(OBJECTS) os_schema.o \
            $(LDLIBS)
       $(OS_POSTLINK) executable
.o  files: .cc f iles 
      ${CCC} $(CPPFLAGS) -c .cc  files 
os_schema.o: os_schema.cc
      $(CCC) $(CPPFLAGS) -c os_schema.cc
os_schema.cc: schema.cc
ossg -assf os_schema.cc -asdb $(APPLICATION_SCHEMA_ PATH) \
$(CPPFLAGS) schema.cc $(OS_ROOTDIR)/lib/libosqry.ldb \ $(OS_ROOTDIR)/lib/liboscol.ldb clean: osrm -f ${APPLICATION_SCHEMA_PATH} rm -f ${EXECUTABLES} ${OBJECTS} os_schema.*

Using Signal Handlers

At run time, ObjectStore sets a handler for the UNIX SIGSEGV signal. On some platforms, it also sets a handler for SIGBUS.

These handlers are critical to ObjectStore's operation. If your application disturbs them, it will fail, and it might fail in a way that makes it difficult to determine why it failed.

If you must temporarily change the state of the handler for SIGSEGV and SIGBUS, be sure to save and restore the complete state. You cannot do this with the signal entry point; you must call sigaction and save the contents of the structure returned as the old handler state.

Makefile for Building from Compilation Schemas

The following makefile fragment shows a less common use of ossg. ossg builds a compilation schema in two steps from two schema source files. It then builds the application schema source file and the application schema database from the compilation schema. Finally, the makefile compiles the application schema source file and links it into the executable. Note that the double colon allows you to define the same target twice.

all: my_exec
my_exec: main.o os_schema.o foo.o bar.o
      CC -o my_exec main.o os_schema.o foo.o bar.o -los
      $(OS_POSTLINK) my_exec
my_exec.cdb:: schema_source1.o
      ossg -csdb my_exec.cdb $(CPPFLAGS) schema_source1.cc
      touch schema_source1.o
my_exec.cdb:: schema_source2.o
      ossg -csdb my_exec.cdb $(CPPFLAGS) schema_source2.cc
      touch schema_source2.o
os_schema.cc: my_exec.cdb
      ossg -asdb my_exec.adb -assf os_schema.cc my_exec.cdb
For more information, see Generating a Compilation Schema.

Establishing Fault Handlers in POSIX Thread Environments

On some UNIX systems, the POSIX thread environment gives each thread its own set of UNIX signal handlers. On such systems, the ObjectStore handlers for SIGSEGV (and in some cases SIGBUS) must be established in each thread.

ObjectStore provides two macros to help you do this:

Affected platforms
On the Digital UNIX, SGI IRIX, and HP-UX platforms, use the OS_ESTABLISH_FAULT_HANDLER and OS_END_FAULT_HANDLER macros at the beginning and end of any thread that performs ObjectStore operations. This is required because HP-UX and Digital UNIX signal handlers are installed strictly on a per-thread basis and are not inherited across pthread_create calls.

A typical function that uses these macros in an ObjectStore application would look like this:

void thread_1(  ) {
      OS_ESTABLISH_FAULT_HANDLER
      ... your code...
      OS_END_FAULT_HANDLER
return  value;
}
Unaffected platforms
The AIX and Solaris 2 platforms do not require the use of these macros because the signal handlers are inherited across pthread_create calls.

You can benefit from using these macros, even on platforms not requiring them. This practice helps ensure portability of code, and also guards against potential problems resulting from future changes to your operating system.

Virtual Function Table Pointers

Virtual function table and discriminant function symbols do not need to be in the base executable. In fact, the schema object file does not have to be in the base executable. It can be in shared libraries.

When ObjectStore is fully initialized, it examines each of the shared libraries specified at link time that was opened by shl_load or cxxshl_load. ObjectStore searches the shared libraries for the symbols that identify the tables in the schema object file. After it finds these symbols, it searches again to find as many vtbls and discriminants as it can.

Debugging Applications

When debugging applications on UNIX systems, be sure to instruct the debugger to send SIGBUS and SIGSEGV signals through to the application. ObjectStore expects to be handed those exceptions, as opposed to having the debugger catch them as if they were errors.

SGI IRIX
On IRIX, the standard debugger is odbx (old dbx) or cvd, which is part of CASEVision/Workshop 2.4 (a layered product).

HP-UX
On HP-UX, the standard debugger is xdb. Specify

z 10 irs
z 11 irs
AIX
On AIX, the standard debugger is dbx. Specify

ignore 10
ignore 11
Digital UNIX
On Digital UNIX, the standard debugger is decladebug. Specify

ignore SEGV
It is not necessary to ignore SIGBUS.

Solaris C++ Search Paths

On Solaris 2 with ProCompiler C++ 4.0.1, the schema generator (ossg) uses a script as the default preprocessor. This script invokes CC and expects to find the ProCompiler C++ 4.0.1 compiler in your search path. If the script finds the wrong CC when called by ossg, you receive a message such as the following. If you correct your search path, this should fix the problem.

/usr/include/stddef.h line 30: syntax error on input" (103)

SGI Delta C++ Compiler

ObjectStore cannot persistently store objects in Delta format. You can use the Delta C++ compiler, but you cannot use ObjectStore to store Delta objects persistently in the database.

Windows

This section provides information you need to compile and link ObjectStore applications using the Microsoft Visual C++ 32-bit edition compiler.

Note that you must use the 32-bit edition of Visual C++.

Linking with ObjectStore Libraries

ObjectStore includes libraries that you must link with when you build your application. Libraries allow multiple programs to share code without redundantly compiling the source. Applications use libraries by specifying them at link time.

On Windows platforms, the only ObjectStore library is ostore.lib. You must link with this library every time you build an ObjectStore application.

Use Custom Build to Run ossg

If you want to run the ObjectStore schema generator within the IDE (Integrated Development Environment), you must use a Custom Build step. This is to add the rules needed to run the ObjectStore schema generator in its automatically generated makefiles.

How to customize Visual C++
To use the Custom Build feature, name your schema source file with an extension other than .cpp or .c, (.osg, for example). Include the schema source file in your project, and set up the Custom Build step appropriately. See the MFC example discussed in Building ObjectStore/Microsoft Foundation Class Applications. Also see Using the Visual C++ Integrated Development Environment (IDE).

Ensure That You Include Required Files

The ObjectStore installation program modifies your INCLUDE environment variable to include the %OS_ROOTDIR%\include directory. Therefore, under normal circumstances, you should not need to specify this directory in a compilation command.

If you edit your environment to remove %OS_ROOTDIR%\include from your INCLUDE environment variable, you must add the following argument to your compilation and ossg commands.

-I%OS_ROOTDIR%\include
If you include in your makefiles the makefile shipped with ObjectStore, %OS_ROOTDIR%\etc\ostore.mak, you can use the makefile macro COMPILER_OPTS to get the proper compilation options.

Make and Compiler Options

Here is an example of a compilation command:

mycode.obj: mycode.cpp 
      cl -c -W3 -EHa -G4 -D_X86_=1 -DWIN32 -MD -Zi -vmg -vmv\
      I$(OS_ROOTDIR)\include mycode.cpp
Requirements
The options -c, -W3, -G4, -D_X86_=1, and -DWIN32 are required in approximately this form by all compilations with Visual C++. You can adjust the warning level lower with -W2 or higher with -W4, but -W3 is the default for Visual C++. You can also optimize for the 386 with -G3 or the Pentium with -G5, but -G4 is the default for Visual C++. You can use any optimization arguments.

The option -MD is required in order for you to use msvcrt.lib, which is required by ObjectStore.

The implementation of TIX exceptions depends on C++ exceptions. All ObjectStore modules should be compiled with the /EHa option. ObjectStore header files that rely on C++ exception handling use a pragma statement to ensure that /EHa is used. If you do not specify /EHa when you compile files that use those headers, you receive an error such as

osdraw.cpp(168) : error C4530: C++ exception handler used, but unwind 
semantics are not enabled. Specify -EHa 
Do not ignore this error.

The option -Zi causes debugging information to be put in the project database. You can also use the -Z7 or -Zd option.

All compiler and linker options not mentioned explicitly can be set as you want.

Use the Standard Run-Time Library on Windows NT

All ObjectStore applications for Windows must link with the standard Visual C++ run-time library msvcrt.lib.

Run-time libraries
Each run-time library has its own allocation (malloc, operator new) and deallocation (free, operator delete) routines. You cannot call an allocator from one library (for example, msvcrt) and deallocate that object in any other library (for example, LIBC.LIB or LIBCMT.LIB).

ObjectStore is linked with msvcrt.lib, which allows ObjectStore to freely allocate objects in any ObjectStore DLL and deallocate them in any other ObjectStore DLL. This is because all ObjectStore DLLs share the single allocator in MSVCRT40.DLL.

Because ObjectStore is linked with msvcrt.lib, it is easy for most applications that also link with msvcrt.lib to deallocate objects that are allocated by ObjectStore APIs (for example, os_collection::query()).

Compiling DLLs
Any part of any application that links against ObjectStore must use msvcrt.lib and only msvcrt.lib as its run-time library. Consequently, you must specify the -MD option when you compile a DLL that calls ObjectStore. This option is not required when you compile other DLLs (your own or obtained from a third party), provided you are careful about the issues surrounding shared C run-time constructs.

You can use a library DLL that is not compiled with the -MD option. Keep in mind that it has a separate copy of the C run-time library and therefore you cannot share certain objects between that DLL and the rest of the application.

Compiling DLLs without msvcrt.lib
When you do not compile a DLL with the -MD option, you cannot share pointers to standard input/output files, C++ streams, and the like. Without the -MD option, there can be conflicts about how to delete a shared object. Some library DLLs (like WSOCK32, the Windows Sockets DLL) were compiled with the -MD option. Others, like MFC, were not, but you can compile them with the -MD option.

If you must link with LIBC.LIB or LIBCMT.LIB, you can do one of two things:

Linking Your Files

After you generate an application schema, you can link the application object files, application schema object file, and ObjectStore libraries to create an executable or dynamic link library (DLL).

Required
The following requirements apply:

Link example
Use a command line like the following, which is shown using the response file syntax used by nmake:

Linking an executable file would look like this:

link @<< 
-NODEFAULTLIB -machine:i386 -subsystem:windows -debug 
-debug-type:cv -out:myapp.exe myapp.obj myschema.obj ostore.lib msvcrt.lib kernel32.lib user32.lib gdi32.lib winspool.lib
<<
Linking a DLL would look like this:

link @<< 
-NODEFAULTLIB -dll -machine:i386 -debug -debugtype:cv 
-out:myapp.dll myapp.obj myschema.obj ostore.lib msvcrt.lib
kernel32.lib user32.lib gdi32.lib winspool.lib 
<<
myschema.obj in the previous two link commands is the application schema object file output from the schema generator (ossg).

In both examples, the %OS_ROOTDIR%\lib directory must be listed in your LIB environment variable. This is normally set up by the ObjectStore installation program.

Sample Makefile

In makefiles, do not specify an existing ObjectStore database as the application schema database. Doing so can corrupt your build process if the Server log has not been propagated to the database.

The schema generator (ossg) is a C++ compiler front end that parses C++ source code to obtain information. This means that you must pass the same compiler flags to ossg as you pass to the compiler when you are compiling your source. It is especially important to duplicate the -I, -D, and -Zp arguments. Also, remember that -MD implies -D_DLL, so pass the -D_DLL to ossg. Note how $(COMPILER_OPTS) is used for both compilation and schema generation in the following makefile fragment.

!include $(OS_ROOTDIR)\etc\ostore.mak
OBJECTS=note.obj
EXECUTABLES=note.exe
APPLICATION_SCHEMA_PATH=note.adb
all: $(EXECUTABLES)
myschema.obj: schema.cc
      ossg -asof myschema.obj -asdb $(APPLICATION_SCHEMA_
PATH) \
            $(COMPILER_OPTS) schema.cc 
note.obj: note.cc
      $(COMPILER) $(COMPILER_OPTS) note.cc
note.exe: $(OBJECTS) myschema.obj
      $(CL_LINK) /OUT:note.exe $(OBJECTS) myschema.obj \
            $(OS_ROOTDIR)\lib\ostore.lib
clean:
      -osrm -f $(APPLICATION_SCHEMA_PATH)
      -del $(OBJECTS) osschema.*

Sample Makefile for an Application That Uses Collections and Queries

The following makefile adds the specification of two library schemas to the preceding makefile. This is for a Windows application that uses collections and queries. Note that in ObjectStore Release 3, you only needed to specify the collections library schema, which included the query library schema. In ObjectStore Release 5.1, if you use both collections and queries, you must specify a library schema for each feature.

Sample file
!include $(OS_ROOTDIR)\etc\ostore.mak
OBJECTS=note.obj
EXECUTABLES=note.exe
APPLICATION_SCHEMA_PATH=note.adb
all: $(EXECUTABLES)
myschema.obj: schema.cc
      ossg -asof myschema.obj -asdb $(APPLICATION_SCHEMA_
PATH) \
            $(COMPILER_OPTS) schema.cc \            $(OS_
ROOTDIR)\lib\osquery.ldb \1
            $(OS_ROOTDIR)\lib\os_coll.ldb2
note.obj: note.cc
      $(COMPILER) $(COMPILER_OPTS) note.cc
note.exe: $(OBJECTS) myschema.obj
      $(CL_LINK) /OUT:note.exe $(OBJECTS) myschema.obj \
            $(OS_ROOTDIR)\lib\ostore.lib
clean:
      -osrm -f $(APPLICATION_SCHEMA_PATH)
      -del $(OBJECTS) osschema.*
Notes on sample file
1Add query library schema.

2Add collections library schema.

Specifying Environment Variables

The following environment variables are automatically set by the ObjectStore installation program:
OS_ROOTDIR

ObjectStore root directory.

PATH

%OS_ROOTDIR%\bin is added to this environment variable.

INCLUDE

%OS_ROOTDIR%\include is added to this environment variable (only for development installations).

LIB

%OS_ROOTDIR%\lib is added to this environment variable (only for development installations).

You can edit these environment variables using the Control Panel System applet.

On Windows NT, ObjectStore adds these variables to the system environment.

Debugging Your Application

Visual C++ debugger
ObjectStore handles all access violations to determine if they are persistent memory accesses. If you handle access violations in the Visual C++ debugger you would disrupt this, so leave this exception unhandled in the debugger. You might see multiple exception messages such as the following:

First-Chance Exception in  yourprog.exe: 0xC0000005: Access Violation.
First-Chance Exception in  yourprog.exe: ( something.DLL) 0xC0000005: 
Access Violation.
You can safely ignore these messages.

Under Debug | Exceptions, the default for exception C0000005 Access Violation is Stop if not handled. Do not change this to Stop Always. If you do, ObjectStore cannot function normally.

Obtaining a stack trace
On Windows NT, to obtain a complete stack trace, use the debug versions of the ObjectStore DLLs.

The debug DLLs are available on the distribution CDROM.

To obtain a back trace using the debug DLLs, put the debug DLL directory in the front of the path environment and then run the msvc debugger.

For example, using myapps on drive C and a CDROM on drive E, you would issue the following commands:

C:\myapps> set path = e:\windows\debnt\bin;%path%
C:\myapps> start msvc myapps.exe
Setting a breakpoint
If your application exits with an unhandled TIX exception, you can set a breakpoint to obtain a stack trace prior to the stack's being unwound. The OS_DEF_BREAK_ACTION environment variable allows you to do this. When you set this variable to 1, ObjectStore reaches a hardcoded breakpoint immediately before an exception is signaled. This works with Visual C++'s just-in-time debugging.

Abnormal Application Exit

In case of abnormal ObjectStore application exits, you might want to get a stack trace at the point of failure before cleanup handlers are run. To do this, you can do one of the following:

This method allows you to set a function to be called before the ObjectStore exception handler unwinds the call stack or exits from the program. You can set a breakpoint in this function and then examine the stack using the Visual C++ debugger. Here is a code sample illustrating how to use this function:

#include <iostream.h>
#include <ostore/ostore.hh>
void break_hook(tix_exception *err, os_int32, char* message){
cout << "Set break point here" << endl;
cout << "Have a look at the stack " << endl;
// You may also want to put up a message box that displays
// the contents of the message parameter.
}
main(int argc, char *argv[])
{      OS_ESTABLISH_FAULT_HANDLER
      os_database *db1;
      objectstore::initialize();
      tix_exception::set_unhandled_exception_hook(break_hook);
      do_something_fun();
      OS_END_FAULT_HANDLER
}

Building ObjectStore/Microsoft Foundation Class Applications

To build ObjectStore/MFC applications, users need to address a number of issues, as described here. (See Generating MFC Applications Using ObjectStore AppWizards for related information.)

  1. Putting OS_ESTABLISH_FAULT_HANDLER and objectstore::initialize code in WinMain.

  2. Putting OS_ESTABLISH_FAULT_HANDLER in threads created with CWinThread::CreateThread.

  3. Integrating ObjectStore's overloading of operator new and delete with MFC's DEBUG_NEW macro.

  4. Adding knowledge of nonmapped persistent pointers to MFC's valid-address checking.

  5. Adding support for persistent new of MFC types.

To ensure that these issues do not cause problems using MFC, add the following to your code.

Issue 1
Resolve issue 1 by copying the function AfxWinMain from MFC\SRC\WINMAIN.CPP to an application source file, and adding the initialization calls to the copy. This will override the AfxWinMain in the unchanged MFC DLL.

Issue 2
Resolve issue 2 by putting the OS_ESTABLISH_FAULT_HANDLER and OS_END_FAULT_HANDLER macros in the thread functions passed to CWinThread::CreateThread.

Issue 3
Resolve issue 3 by modifying stdafx.h as follows. The reason for doing this is that MFC uses #define new DEBUG_NEW to activate the MFC debugging malloc, and that causes problems for the ObjectStore overloadings of new. To eliminate these problems, redefine DEBUG_NEW to be new as opposed to new(__FILE__,__LINE) and then insert an inline operator delete that calls ObjectStore's internal persistent delete function. This, in turn, checks for transient pointers and calls _ODI_free if needed.

To do this, add the following to stdafx.h after including ostore.hh and afxwin.h:

// If we let DEBUG_NEW keep the definition that it's given in 
// afxwin.h, 
// and let the "#define new DEBUG_NEW" from afx.h stay, then our
// overloadings of new won't be recognized by the compiler.
      #ifndef _AFX_NO_DEBUG_CRT
      #ifdef DEBUG_NEW
      #undef DEBUG_NEW
      #define DEBUG_NEW new
      #endif
      #ifdef new
      #undef new
      #define new new
      #endif
      #endif
Then, add the following at the end of stdafx.h:

// This declaration taken from ostore.h */
extern "C" void _OSSYSCALL objectstore_delete(void *);
// In DEBUG mode, MFC has its own operator delete. We need to get
// first dibs on the deletion if the thing being deleted is persistent.
//
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
inline void operator delete(void* p)
      {
      objectstore_delete(p);
}
      #endif
Issue 4
Resolve issue 4 by never passing persistent data to library calls. Pass copies instead.

Issue 5
Resolve issue 5 by not storing MFC classes persistently. See Class os_CString below.

Class os_CString

ObjectStore provides a shadow class of CString called os_CString that does the job of storing CString objects persistently. These classes can be used interchangeably for most purposes.

Class os_CString has the same layout and member functions, but it includes get_os_typespec() members and cast-to-CString members. This means that users can easily pass them from the database to MFC and back. To use os_CString, include <ostore/oscstring.h> in your source code.

You can find the source code for os_CString in the directory %OS_ROOTDIR%\examples\ospmfc.

Generating MFC Applications Using ObjectStore AppWizards

ObjectStore includes a custom AppWizard for VC++ 5.0. This wizard can be used to generate MFC applications that use ObjectStore.

When an application is generated with this wizard, all the code needed for ObjectStore is inserted into your project. The following is what is inserted in addition to standard code provided by VC++:

Ensure that the following environment variables are set:

These are set by ObjectStore installation.

The source code for the ObjectStore AppWizard can be found in the directory %OS_ROOTDIR%\examples\ostoreaw.

Using the AppWizard
Complete the following sequence to create an ObjectStore MFC application with the AppWizard:

  1. Start Microsoft Developer Studio.

  2. In the File menu, select New.

  3. From the dialog box displayed, select the Projects tab and select ObjectStore AppWizard.

  4. Enter the project name and click OK.

  5. In these steps, select the MFC-specific options you prefer.

  6. Check Use ObjectStore Collections if you want your application to use ObjectStore collections. This will include collections-related files and initialize ObjectStore collections at the right place.

  7. Click on Finish to generate a project with correct ObjectStore include files and initializations.

Read the readme.txt file provided with this new project and make changes as described there. This project also copies a file schema.scm in your project. This is a skeleton for a schema file needed for ObjectStore. You can change this file and add ossg compilation options in your project, as described in the readme.txt provided in the project.

Manual steps
The ObjectStore AppWizard cannot add the schema compilation build step to the project. You must do this following the directions in readme.txt.

You must add OS_ESTABLISH_FAULT_HANDLER to the top-level threads functions when using threads.

Using the Visual C++ Integrated Development Environment (IDE)

Follow these steps to use the VC++ IDE to generate schema.

  1. Choose a file name extension for your schema source file other than .cpp, for example, .osg.

  2. Set up a Custom Build rule that specifies that the schema object file is to be built from the schema source file, by using the command

      ossg < other ossg args> schema.osg
The ObjectStore MFC example is set up to use this technique.

Using ObjectStore Within a DLL

This section provides examples of how to use ObjectStore in a DLL.

In the directory %OS_ROOTDIR%\examples\dll, there are two subdirectories, LIBSCHM and NOSCHM. These two directories demonstrate two ways to use ObjectStore from within a DLL.

Each of these two directories contains two subdirectories, PROG and LIB. The LIB directory creates a DLL called people.dll that uses ObjectStore. The PROG directory creates a program that uses people.dll.

The difference between the directories LIBSCHM and NOSCHM is as follows:

This approach is useful if you are in a development environment where a single person or a small group of people are the only developers using ObjectStore, or if your product is a persistent library that will be used by developers who do not have any knowledge of ObjectStore.

Building Applications on Machines Remote from the Server

You can build an application on a machine that is remote from the ObjectStore Server.

All databases, including application schemas and library schemas, must physically reside on the same machine as the Server. The schema generator expects to be able to connect to a Server and produces an error message if it cannot do so. Consequently, you must provide the schema generator with a Server-relative pathname. There are two ways to do this.

You can specify ObjectStore Server-relative pathnames even if you are not using NFS or another file-sharing option. This does not rely on any file system protocol. Instead, this syntax is recognized by ObjectStore tools. Using Server-relative pathnames, the ossg command line would look like this:

Example 1
ossg -asdb foo:c:\appdir\appschema.adb -assf osschema.cc /
      -cd schmdefs.hh myschema foo:c:\ostore\lib\os_coll.ldb
This example assumes that

This method makes no assumptions about the availability of a remote file system protocol.

If you can use Windows networking to connect to a network drive on the Server, you can use pathnames that start with that network drive letter.

Example 2
If you are on a system that supports NFS, you can mount a directory on the Server as follows:

nfs use x: bar:/usr
This mounts the /usr file system of a remote Server machine called bar on the local directory x. Having done that, you use the following form for your ossg command line:

ossg -asdb x:\appdir\appschema.adb -assf osschema.cc \
      -cd schmdefs.hh myschema.cc x:\ostore\lib\os_coll.ldb \
      x:\ostore\lib\os_query.ldb
This example assumes that

Porting ObjectStore Applications to Windows Platforms

This section presents guidelines for porting ObjectStore code to a Windows environment.

Macros for fault and exception handling
ObjectStore must handle all memory access violations, because some of those access violations are actually references to persistent memory in an ObjectStore database. On UNIX systems, ObjectStore can register a signal handler for such access violations. But on Windows, there is no function for registering a handler that also works when you are debugging an ObjectStore application; the SetUnhandledExceptionFilter function does not work when you are using the Visual C++ debugger.

Therefore, every ObjectStore application must put a handler for access violations at the top of every stack in the program. This normally means putting a handler in a program's main or WinMain function and, if the program uses multiple threads, putting a handler in the first function of each new thread.

ObjectStore provides two macros to use in establishing a fault handler:

These macros expand to nothing on platforms that do not require their use. Using these macros, a typical main function in an ObjectStore application would look like this:

int main (int argc, char** argv) {
      OS_ESTABLISH_FAULT_HANDLER
      ... your code...
      OS_END_FAULT_HANDLER
return  value;
}
A WinMain function would also look like the preceding example.

Threads
You must use the Visual C++ C run-time functions _beginthread and _endthread, as they properly initialize the Visual C++ C run-time library. CreateThread and TerminateThread do not properly initialize the Visual C++ C run-time library.

objectstore::initialize() need only be called once, even though an application has multiple threads.

long double and warning C4069
Visual C++ makes doubles and long doubles the same size (eight bytes) and issues a warning whenever a long double is encountered. For example:

c:\ostore\include\ostore\mop.hh(1041) : warning C4069: long double is 
the same precision as double
To avoid these warnings, ObjectStore header files use pragma statements that disable them. You can enable this warning for your code by adding the following after the ObjectStore include files:

#pragma warning ( default : 4069 )
/NODEFAULTLIB option
The default libraries should not be used with multithreaded programs. The /NODEFAULTLIB or /NOD option tells the Visual C++ linker not to search the default libraries. During compilation, you can use the /Zl (lowercase l as in library) option to suppress default library search records in the object files.

Windows DEBUG and DDEBUG Builds of ObjectStore

The build of ObjectStore for Windows installed by the SETUP program is a retail release that was compiled optimized, without extra error checking and without debugging symbols, to make the smallest, most efficient installation package. Two debugging versions of ObjectStore that you can install manually to aid in debugging your applications are also included.

debug
The debug build is a drop-in replacement for the retail build, and can be used to obtain symbolic stack trace information that can help you debug your application or that might be required by Object Design Technical Support to track down a problem. It is compiled unoptimized, and has some extra error-checking code built in.

ddebug
The ddebug build uses the debugging version of the Visual C++ run time, and so is compatible with the debug versions of the Microsoft Foundation Class and Visual C++ libraries. This build is most useful to application developers who are building and debugging a new application, because they can symbolically debug an entire application, including the run-time and MFC libraries, if used.

Installing DEBUG.ZIP or DDEBUG.ZIP

To install DEBUG.ZIP or DDEBUG.ZIP, follow these steps:

  1. Install ObjectStore Release 5.1 with the SETUP program. See ObjectStore installation for Windows NT documentation for instructions.

  2. Shut down the ObjectStore Server and Cache Manager by using the ObjectStore SETUP program. Answer Yes to the question about shutting down servers, then exit from SETUP.

  3. Go to the %OS_ROOTDIR% directory.

  4. Rename bin and binsngl directories (from the command prompt window or Windows Explorer) to retail.bin and retail.binsngl.

  5. Unzip the file (DEBUG.ZIP or DDEBUG.ZIP) from the command prompt by typing the following command.The -d option creates and restores the directories included in the zip file.

          pkunzip -d debug.zip 
    
  6. Run the ObjectStore SETUP program to start the Server. In the first setup dialog, select the Setup Server option. In the menu Choosing to start ObjectStore services automatically, select Yes. Then a Confirm Message dialog asks if you want to start the services right now. Select Yes.

To use the retail or debug builds, compile your application using the /MD switch. Using Project | Settings in Developer Studio, select C/C++, Category Code Generation, Use runtime library Multithreaded DLL. This automatically selects ostore.lib as a default library. You can then switch between retail and debug builds by changing your PATH.

To use the ddebug build, install the ddebug libraries as directed in Installing DEBUG.ZIP or DDEBUG.ZIP. Then compile your application using the /MDd switch. Using Project | Settings in Developer Studio, select C/C++, Category Code Generation, Use runtime library Debug Multithreaded DLL. This automatically selects ostored.lib as a default library. To run the resulting application, ensure that the ddebug build is in your PATH.

The following table compares the features of retail ObjectStore, debug, and ddebug:
CharacteristicRetail debug ddebug
Installation with INSTALL?

Yes

No

No

Optimized?

Yes

No

Yes

ObjectStore symbols available?

No

Yes

Yes

Drop-in capability?

Yes

Yes

No

Compiling and linking applications
Use the following information when compiling and linking applications:
Retail debug ddebug
Run-time libraries (DLL)

msvcrt.dll

msvcrt.dll

msvcrtd.dll

Compile Options

/MD

/MD

/MDd *

Link Library

ostore.lib

ostore.lib

ostored.lib

ObjectStore libraries (DLLs)

O4....DLL

O4....DLL

D4....DLL

* The /MDd option defines the symbol _DEBUG, which determines the link library used by ObjectStore.

OS/2

This section provides information about compiling and linking ObjectStore applications using the VisualAge C++ compiler, icc, on OS/2.

Using Compiler Options

Required
You must always use these compiler options:
/Gd

Dynamically link run-time library

/Gm

Multithreaded libraries

Prohibited
You cannot use these compiler options with ObjectStore:
/Gr

Device driver

/Rn

Subsystem environment

You cannot use these compiler options when compiling code that includes ObjectStore header files:
/EHa

No exception support

/H

Short external names

/Ms

Use _System calling sequence

/Sc

Use cfront language standard

/Sg

Set margins

/Sp

Pack structures

/Sq

Use sequence numbers

Specifying default language for files
Use /Tdp to compile all source and unrecognized files that follow on the command line as C++ files. You can specify /Td anywhere on the command line to return to the default rules for the files that follow it.

No rules
There are no rules for compiler and linker options not explicitly mentioned. You can decide how to set them.

Note: Previous releases of ObjectStore on OS/2 required the /Su4 compiler option. While it is not required for ObjectStore Release 5.1 applications, you must continue to specify it if you want your application to be compatible with databases that were created with ObjectStore Release 3. The /Su4 option is required for compatibility whether or not you upgraded your databases to be ObjectStore Release 5.1 databases. An alternative to specifying this option is to perform schema evolution on the existing databases.

Linking Your Files

After you generate the application schema, you can link your application object files, ObjectStore libraries, and the application schema object file into an executable.

Required library
You must link ObjectStore applications with the library ostore.lib. To do so, you can either add %OS_ROOTDIR%\lib to your LIB environment variable and put ostore.lib on the link command line, or you can put %OS_ROOTDIR%\lib\ostore.lib on the link command line.

The reference to ostore.lib can be anywhere on the link command line as long as it appears before any explicit references to CPPOM30I.LIB (the C++ run-time library).

You must call the function objectstore::initialize() before calling any other ObjectStore interface function.

Case sensitivity
ObjectStore applications run correctly whether or not linking is case sensitive. Object Design recommends case-sensitive linking.

Compiling the application schema source file
You must compile the application schema source file produced by ossg into an object file. This file includes ObjectStore header files and none of your header files, so the compilation command line is simple. For example:

icc /C /Gd /Gm myschema.cpp
This produces a file named myschema.obj.

Linking object files into an executable
A typical link command line is

icc /Tdp /B"STACK:32768" /Femy_exec.exe myschema.obj \ my_
ob1.obj my_ob2.obj %OS_ROOTDIR%\lib\ostore.lib 
Sample makefile
In makefiles, do not specify an existing ObjectStore database as the application schema database. Doing so can corrupt your build process if the Server log has not been propagated to the database.

myschema.obj: myschema.cpp
      ossg -assf myschema.cpp -cd schmdefs.hh -asdb 
myschema.adb \
            myschema $(OS_ROOTDIR)\lib\os_coll.ldb
      icc /C /Gd /Gm myschema.cpp
my_exec.exe: my_exec.obj myschema.obj 
      icc /Tdp /B"STACK:32768" /Femy_exec.exe my_exec.obj \
            myschema.obj $(OS_ROOTDIR)\lib\ostore.lib 

Sample Makefile Without Library Schemas

OBJECTS=note.obj
EXECUTABLES=note.exe
APPLICATION_SCHEMA_PATH=note.adb
all: $(EXECUTABLES)
myschema.obj: myschema.cc
      icc /C /Gd /Gm /Ti myschema.cc
myschema.cc: schema.cc
      ossg -assf myschema.cc -cd schmdefs.hh \
            -asdb $(APPLICATION_SCHEMA_PATH) \
            $(CPPFLAGS) schema.cc 
note.obj: note.cc
      icc /C /Gd /Gm /Ti note.cc
note.exe: $(OBJECTS) myschema.obj
      icc /Tdp /B"STACK:32768" /Fenote.exe $(OBJECTS) 
myschema.obj \
      $(OS_ROOTDIR)\lib\ostore.lib
clean:
      -osrm -f $(APPLICATION_SCHEMA_PATH)
      -del $(OBJECTS) osschema.*

Sample Makefile for an Application That Uses Collections and Queries

The following makefile adds the specification of two library schemas to the previous makefile. This is for an OS/2 application that uses collections and queries. Note that, in Release 3, you only needed to specify the collections library schema, which included the query library schema. In ObjectStore Release 5.1, if you use both collections and queries you must specify a library schema for each feature.

OBJECTS=note.obj
EXECUTABLES=note.exe
APPLICATION_SCHEMA_PATH=note.adb
all: $(EXECUTABLES)
myschema.obj: myschema.cc
      icc /C /Gd /Gm /Ti myschema.cc
myschema.cc: schema.cc
      ossg -assf myschema.cc -cd schmdefs.hh \
            -asdb $(APPLICATION_SCHEMA_PATH) \
            $(CPPFLAGS) schema.cc \
Add query library schema
Add collections library schema
            $(OS_ROOTDIR)\lib\osquery.ldb \
            $(OS_ROOTDIR)\lib\os_coll.ldb
note.obj: note.cc
      icc /C /Gd /Gm /Ti note.cc
note.exe: $(OBJECTS) myschema.obj
      icc /Tdp /B"STACK:32768" /Fenote.exe $(OBJECTS) 
myschema.obj \
      $(OS_ROOTDIR)\lib\ostore.lib
clean:
      -osrm -f $(APPLICATION_SCHEMA_PATH)
      -del $(OBJECTS) osschema.*

Debugging Your Application

By default, IPMD halts for every memory exception and asks whether to proceed. Because ObjectStore applications take memory exceptions regularly in the course of persistent storage management, it is often convenient to disable this behavior.

You can do this by using the OS/2 environment variable PMDEXCEPT. When this environment variable is set to 1, the debugger unconditionally passes ObjectStore exceptions to ObjectStore.

However, if your application fails with a general protection fault, setting PMDEXCEPT causes the program to exit before you can debug the error.

If you need to debug this kind of problem, set a breakpoint on the first instruction in O4LOW.DLL. This breakpoint occurs only if there is a general protection fault that ObjectStore declines to handle (such as dereferencing a null pointer).

Obtaining a stack trace
To obtain a complete stack trace, use the debug versions of the ObjectStore DLLs. The debug DLLs are available on the distribution CDROM.

To obtain a back trace using the debug DLLs, put the debug DLL directory in the front of the LIBPATH environment, reboot, and then run the IPMD debugger.

Pass Source Files to ossg

If you pass object modules instead of source modules to ossg on the command line, the schema generator displays a parsing error. Be sure to pass source modules to ossg.

Building Applications on Machines Remote from the Server

You can build an application on a machine that is remote from the ObjectStore Server.

All databases, including application schemas and library schemas, must physically reside on the same machine as the Server. The schema generator expects to be able to connect to a Server and produces an error message if it cannot do so. Consequently, you must provide the schema generator with a Server-relative pathname. There are two ways to do this.

You can specify ObjectStore Server-relative pathnames even if you are not using NFS or another file sharing option. This does not rely on any file system protocol. Instead, this syntax is recognized by ObjectStore tools. Using Server-relative pathnames, the ossg command line would look like this:

Example 1
ossg -asdb foo:c:\appdir\appschema.adb -assf osschema.cc /
      -cd schmdefs.hh myschema foo:c:\ostore\lib\os_coll.ldb
This example assumes that

This method is preferable to the file sharing method because it is more portable. It makes no assumptions about the availability of a file system protocol.

Example 2
If you are on a system that supports NFS, you can mount a directory on the Server as follows:

mount x: foo:c:\
This mounts the C drive of a remote Server machine called foo on the local directory x. Having done that, you use the following form for your ossg command line:

ossg -asdb x:\appdir\appschema.adb -assf osschema.cc \
      -cd schmdefs.hh myschema.cc x:\ostore\lib\os_coll.ldb \
      x:\ostore\lib\os_query.ldb
The same assumptions apply here as in the previous example.



[previous] [next]

Copyright © 1998 Object Design, Inc. All rights reserved.

Updated: 03/26/98 19:59:13