Chapter 1
Porting SCO OpenServer 5 Applications
to SCO OpenServer 6
This document describes porting SCO OpenServer Release 5 applications to Release 6, and techniques that can be used to make such a port successful.
1.1 About porting SCO OpenServer 5 applications
Porting applications to SCO OpenServer 6 is not difficult. Many ports will involve no more than making a few changes to a makefile, then recompiling and using the SCO OpenServer 6 Development System (Dev Sys).
Porting may not even be necessary:
- An application that uses only SCO-supported Release 5 interfaces should run unmodified on Release 6.
- An application that uses third-party interfaces not supported by SCO may still run unmodified on Release 6 if all required libraries are installed on the Release 6 system along with the application.
But you may want to recompile your application on SCO OpenServer 6 to take advantage of new features such as multithreading or large files, to gain better runtime performance, to access new resources on Release 6, or for other reasons.
The SCO OpenServer 6 Development System allows you to compile programs using either the Release 5 ABI or the Release 6 ABI, as described in the following section.
1.1.1 Compiler ABI modes: UDK and OSR5
SCO OpenServer 6 is designed to run both SCO OpenServer Release 5 (OSR5) ABI applications as well as System V Release 5 (SVR5) applications. These two kinds of applications are distinct because they:
- make different kinds of system calls to the operating system
- make use of different application programming interfaces (APIs)
- embody different application binary interfaces (ABIs).
The OSR5 ABI is the interface supported by SCO OpenServer Release 5 systems, while the SVR5 ABI is the default ABI for Release 6 (and for future OpenServer development). It is also the ABI supported by the UnixWare/OpenServer Development Kit (UDK) and so is sometimes called the UDK ABI.
Within any one operating system process, every object file must have been compiled using either the OSR5 ABI or the SVR5 ABI; this applies to the application and all the libraries it uses. These ABIs cannot be mixed within a single process.
The C compiler (cc command), the C++ compiler (CC command), and a few other development tools include a -K option to select the ABI (or mode), with udk representing the SVR5 ABI and osr specifying the OSR5 ABI.
The default ABI used (i.e., when no -K option is specified) depends upon how the compilers and related tools are invoked. For example:
/usr/ccs/bin/cc default is UDK mode; use -K osr for OSR5 mode (OSR5 ABI) /osr5/usr/ccs/bin/cc default is OSR mode; use -K udk for UDK mode (SVR5 ABI) In general, which ABI you use when you port your application to Release 6, depend on the considerations listed in the following table:
For more information about using these compiler modes, see the Dev Sys overview at: http://osr600doc.sco.com/en/SDK_oview/DEVSYS.oview.html">http://osr600doc.sco.com/en/SDK_oview/DEVSYS.oview.html.
1.1.2 Mixed mode issues
If you have an existing SCO OpenServer 5 application that you want to modernize with threads or large files or some other SVR5-dependent feature, you must compile it in UDK mode. Because UDK mode features some different APIs from SCO OpenServer 5, it is possible that you will have some porting work and source code modifications to do. Occasionally the mode requirements may present a contradiction: for instance, you have an existing SCO OpenServer 5 application program that depends upon and is linked against a third-party library archive. Now you want to modify another part of this program to handle large files. That means you need to use UDK mode, but the presence of the third-party library means you need to use OSR mode. Assuming you cannot get the library vendor to re-build it in UDK mode, what do you do?
In this situation you must split your application program into two processes. One process makes the calls to the third-party library and is compiled in OSR5 mode. The other process makes the calls to do the large file I/O and is compiled in UDK mode. Then you must use some sort of inter-process mechanism (such as sockets, pipes, or IPC) to communicate between the two processes.
1.2 Tool sets supported
The SCO OpenServer 6 Development System (Dev Sys) is found on SCO OpenServer 6 Installation CD-ROM in the media kit. The Dev Sys offers:
- the best integration with SCO OpenServer 6
- generally the best performing generated code (in terms of size and speed)
- a stronger debugger
- the best ability to have the resulting binaries run not just on SCO OpenServer 6, but SCO OpenServer 5 and UnixWare 7 as well.
1.4 Compiler option guidelines
Basic compiler options are defined by POSIX and tend to be the same across platforms (such as -c and -P). Others are trickier and can lead to porting problems. Here are some of the more common problems:
- Link with the right command. Some existing makefiles from SCO OpenServer 5 will link C or C++ programs with ld or link C++ programs with cc, neither of which work with SCO OpenServer 6. Always use cc to link C programs and CC to link C++ programs (if the program is a mixture, use CC). The same is true if you are linking dynamic libraries (.so files). In this case, also use the -G -KPIC options to indicate you want a dynamic library with relocatable code. (Using the -s option that some systems use for this will generate a stripped library that has no debug information.) For both C and C++, much more is done during the link step than simple linking. For C, which now uses DWARF II for debug information, debug abbreviation tables are brought in. For C++, template instantiation prelinking is performed, static constructor and destructor sequences are anchored, and so on. As a rule, using ld directly is inappropriate except when using ld -r to create a conglomeration of object files.
- Do not add -lc or -lC to the link command line. This is sometimes present in makefiles, but the order in which system libraries are linked is critical. The cc and CC commands do this automatically - do not call these libraries explicitly (the compiler will generate a warning).
- Use -Kthread or -Kpthread instead of -lthread. Multithreaded applications frequently use makefiles that pass -D_REENTRANT, -D__THREADSAFE, or some other such symbol to compilers, and then link with -lthread. On SCO OpenServer 6, both C and C++ use a -Kthread (for SVR4 threads) or -Kpthread (for POSIX threads) option at preprocessing, compile, and link time to indicate that multithreading is active.
- Using -lthread will cause problems (and the compiler will generate a warning), because of the system library ordering problem discussed previously.
- Use dynamic links, not static. Applications work best on SCO OpenServer 6 when they are dynamically linked against system libraries instead of linked statically. This ensures the appropriate version of a library is used. (This is why there are no static versions of system libraries like libsocket and libnsl.) If you must link statically, use -dn and not -Bstatic. The latter might have the desired effect with some other compilers, but its meaning in SCO OpenServer 6 is different (it toggles the way the linker looks for libraries) and using it improperly usually causes a runtime failure.
- Be aware of assumptions about symbol exporting. On some UNIX platforms (notably Solaris) the linker exports all global symbols defined in an executable. This means that shared libraries will see those symbols, even if the libraries are dlopen'd during runtime. In SCO OpenServer 6, the linker only exports those symbols defined in an executable that are referenced in the shared libraries seen during the link. That means that if a library is dlopen'd during runtime, it will not see any other symbols that may have been defined in the executable. If these symbols are needed, they should be explicitly exported by passing in the -Wl,-Bexport=name option to the linker. Simply passing -Wl,-Bexport will cause the linker to match the Solaris default behavior.
- Libraries for graphical apps. For SCO OpenServer 6, there is a list of libraries that must be named to link a Motif application: -lXm -lXt -lXext -lX11 -lSM -lICE -lsocket -lnsl Most makefiles from other compilers do not have all these libraries named. If they are not specified, unresolved symbols will result.
- Libraries for networking apps. For SCO OpenServer 6, the order of networking libraries is significant. It should be done like this:
[ -lresolv ] -lsocket -lnsl
- This means libresolv need not be present, but should go first if it is used. The other two are mandatory and should be used in the order shown.
1.5 API issues
In general, SCO OpenServer 6 is compliant with POSIX, XPG4, UNIX 95, and UNIX 98. If the application being ported is also compliant to these standards, a simple recompile and relink should be all that is necessary. In reality, things are rarely that easy. Kernel and API compatibility issues may affect the ability of your application to run as expected on Release 6. These issues are described in the section "Kernel and API Compatibility Notes" on page 23.
1.6 C language dialect issues
- Generally, the Dev Sys C compiler accepts any ISO-standard C code. In default mode, this also includes accepting K&R C dialect (but using ISO semantics where there is a difference). You can give those cases K&R semantics using the cc -Xt transition compilation option. This is usually done to preserve "unsigned-preserving" integral promotion rules (versus the standard "value-preserving" integral promotion rules). Do not use cc -Xt unless you must. It is better to bring code up to date since using cc -Xt can result in a significant performance loss (due to the lack of the volatile attribute).
- Another porting problem occurs for code that assumes a particular signedness of "plain" char. By default, the Dev Sys compiler takes them as signed; the default can be changed to unsigned using the -Kuchar option.
- The Release 5 Dev Sys C compiler's -Xk option for K&R mode is not supported by the Release 6 Dev Sys C compiler; use -Xt instead. In addition, the OSR5 C compiler's -Xm option for `Microsoft mode' is obsolete and no longer supported.
- Note that the Dev Sys C compiler fully supports 64-bit integers via the long long type.
- The most frequent source of C dialect problems comes from gcc-built applications. The GNU C compiler has a number of extensions in it that are not supported on other platforms. The most well-known of these is support for variable-sized arrays:
int length(void); int foo(void) { int x=length(); char f[x]; ... }
- This feature is present in a somewhat different form in the ANSI/ISO 1999 C standard, but is not supported in the Dev Sys C compiler. This means the code must be rewritten using heap allocation.
- Another change brought about by the C 99 standard is that inline and restrict are now C keywords. If this conflicts with existing code and it is not practical to modify the code, the Dev Sys cc -Xb option can be used to suppress the recognition of these two new keywords.
1.7 C++ language dialect issues
The ANSI/ISO 1998 C++ standard invalidated a lot of old, existing C++ code. The following are a few of the better-known examples:
- new keywords
- for loop variable scope change
- template specialization syntax, guiding declarations
- template friends syntax change
- new failure throws exception
- implicit int gone
A more detailed discussion of some of these incompatibilities can be found in newer C++ textbooks, such as Bjarne Stroustrup's The C++ Programming Language (Third Edition), or in the Internet McCluskey C++ Newsletter.
So how do you get existing C++ code bases to compile using the Dev Sys compiler? For many years the original AT&T cfront was the most heavily used C++ compiler. For existing cfront-built code, there is a Dev Sys CC -Xo compatibility option that provides cfront source compatibility. But this also enables cfront bug tolerance and many anachronisms. There are some instances of cfront that CC -Xo will not detect or accept. It is intended as a transitional tool for converting code to the modern dialect of C++ acceptable by the Dev Sys C++ compiler. It should not be used on a permanent basis.
For example, consider this code:
template <class T> class A { int m, n; int explicit; public: void f(); T g(); }; template <class T> void A<T>::f() { for (int i = 0; i < 10; i++) n += i; for (i = 0; i < 10; i++) m += i; } char A<char>::g() { return `a'; } int main() { A<int> a; a.f(); }This compiles under a cfront-era C++ compiler without problems, but generates many errors with the Dev Sys C++ compiler. The same code source compiles without error under the Dev Sys C++ compiler using the -Xo option.
Most ANSI/ISO source language incompatibilities are not complicated and can be straightforwardly resolved, so in most cases it is best to bring the code up to date. In this case, it's simply a matter of avoiding the new keyword, using the new template specialization syntax, and adjusting to the new for loop variable scope rule.
Here is the new version with three simple edits that compiles properly on the OSR6 Dev Sys C++ compiler without using any compatibility option:
template <class T> class A { int m, n; int is_explicit; // changed public: void f(); T g(); }; template <class T> void A<T>::f() { for (int i = 0; i < 10; i++) n += i; for (int i = 0; i < 10; i++) // changed m += i; } template<> char A<char>::g() { return `a'; } // changed int main() { A<int> a; a.f(); }1.8 Changes to the runtime environment
The subsections that follow discuss changes to the runtime environment in SCO OpenServer Release 6 that must be taken into account when porting any Release 5 application. Your application may also encounter runtime issues related to other changes in the runtime environment between Release 5 and Release 6. See the Upgrade Guide at http://www.sco.com/support/docs/openserver/600/migration for more information on changes to the runtime environment in Release 6.
- Note: While the SVR5 ABI is the default runtime binary interface, the SVR5 kernel recognizes OSR5 ABI applications and runs them in the environment that OSR5 ABI applications expect. There are no special steps or commands needed to run an application on Release 6 that was compiled using OSR5 mode (or compiled on Release 5).
1.8.1 Runtime commands
If a Release 5 application requires Release 5 runtime commands (that is, it fails using the default command reached by the default PATH variable on OpenServer 6), Release 5 commands are supplied in the directory /osr5/bin. Change the PATH variable for the application so that it accesses binaries under /osr5/bin before other command directories. Note that manpages for these commands are not provided on the system; access them on the OpenServer 507 doc web site: http://osr507doc.sco.com">http://osr507doc.sco.com.
1.8.2 Runtime access of system/data files
Although links have been used to minimize problems associated with changes of location of system files accessed by applications at runtime, some applications that depend on the internal format of files may experience problems interpreting file contents. One example is the default /bin/cpio command, which uses an "Extended cpio File Format", instead of the "ASCII cpio format" used by the cpio command on OpenServer 5. If your application requires the OpenServer 5 cpio file format, then you'll need to change your application to access the /osr5/bin/cpio version of cpio as described in the last section.
1.8.3 NETbios/NETbeui
NETbios/NETbeui are no longer supported; runtime calls to NETbios commands and references to NETbios resources will fail on SCO OpenServer Release 6.
1.8.4 XENIX 286 emulators
Calls to the legacy i286emul/x286emul runtime emulators and references to associated resources will fail on OpenServer 6.
1.9 Binary debugging
SCO OpenServer Release 6 includes a number of tools for debugging. The sections that follow discuss some of these features in more detail.
1.9.1 Tracing system calls with truss
SCO OpenServer 6 includes a useful command named truss that can trace the system calls made by an application. Using truss does not require recompilation, relinking, access to the source code, or even a symbol table. The truss command replaces the Release 5 trace and scotruss commands.
$ cat fstab.c #include <stdio.h> int main() { FILE* fp = fopen("/etc/fstab", "r"); if (!fp) fprintf(stderr, "*** cannot open file\n"); fclose(fp); } $ cc fstab.c $ ./a.out *** cannot open fileThe program fails because SCO OpenServer 6 uses /etc/vfstab not /etc/fstab, but the error message does not indicate the file it failed to open. Running the program through truss displays each system call, along with its arguments and the return code:
$ truss ./a.out execve("./a.out", 0x08047570, 0x08047578) argc = 1 open("/etc/fstab", O_RDONLY, 0666) Err#2 ENOENT *** cannot open file write(2, " * * * c a n n o t o".., 21) = 21 _exit(-1)In a large program (especially one you are not that familiar with), truss can help you determine the point of failure. Using the -f option, truss can follow child processes as well as the parent process. You can also use truss to grab and release existing processes on the system.
Along with knowing symbolic names for many manifest constants (the O_RDONLY above, for example), truss can display additional information to further focus the trace. An explicit list of system calls to trace (or not to trace) can be given to truss with the -t option.
The -a and -e options respectively cause truss to display all the passed arguments and the entire environment at an exec.
Another advantage is that truss knows structures that cross the system call boundary. Using the -v option, you can specify system calls for which you want to see complete structures displayed.
Finally, all of the data read and/or written on a file descriptor (instead of the default first few bytes) can be displayed using the -r and/or -w options.
$ truss -w2 ./a.out execve("./a.out", 0x08047570, 0x08047578) argc = 1 open("/etc/fstab", O_RDONLY, 0666) Err#2 ENOENT *** cannot open file write(2, 0x08047C14, 21) = 21 * * * c a n n o t o p e n f i l e\n _exit(-1)Note that you must be root to run truss on privileged programs.
1.9.2 Using the dynamic library tracing feature of the runtime linker
A feature similar to truss is provided for dynamic executables by the runtime linker in SCO OpenServer 6.
When a dynamic executable calls a function that (potentially) is defined elsewhere -- outside of the calling shared library or executable -- a call is actually made to a bit of code in the "procedure linkage table" (PLT). This code then does an indirect branch to the target function. But, at process startup (by default), all the PLT entries end up branching to the runtime linker, which searches the executable and the current set of shared libraries for the actual definition of the target function. Once found, the runtime linker modifies the destination of the indirect branch for that PLT entry so that it jumps to the actual function.
Dynamic library tracing takes advantage of this lookup process and interposes a reporting function between the caller and the callee. It can also insert a bit of code to return to that comes between the callee and the caller that similarly reports the return value of the function.
As with truss, dynamic library tracing is disabled for processes that gain privilege for obvious security reasons.
This tracing differs from truss in a number of ways:
- Because each function can call further functions, the call and return are displayed separately.
- The runtime linker only knows a name to search for and (when found) the address. It does not inherently understand anything else about a function, while truss has knowledge of each system call. However, if the defining library provides a special table of encoded bits with an entry for this function, the reporting code will be able to do something other than just print a few hexadecimal words that might be actual arguments. Only the C and threads libraries provide this table. (Note that if an entry is found, the reporting code can cause the process to die if it attempts to dereference a bad string pointer.)
- The runtime linker can only report functions that go through its lookup processing (internal function calls are not reported).
- The reporting code also displays the caller of each function.
Dynamic library tracing is enabled by running a process with certain environment variables set:
Tracing the same fstab.c example from above:
$ LD_TRACE=sym ./a.out atexit(0x80483b4) from 0x8048459 atexit(0xbff9b09c) from 0x8048465 atexit(0x8048514) from 0x804846f __fpstart() from 0x804847b fopen("/etc/fstab","r") from 0x80484b1 _findiop() from _realfopen+7 _open("/etc/fstab",0x0,0x1b6) from endopen+141 __thr_errno() from _cerror+29 fprintf(0x80495ec,"*** cannot open file"...,0x0,0x8047cb8,0x8048485) from 0x80484cc _findbuf(0x80495ec) from fprintf+116 _xflsbuf(0x8047c44) from _idoprnt+358 _write(2,0x8047c04,21) from _xflsbuf+89 *** cannot open file fclose(0x0) from 0x80484d7 exit(-1) from 0x804848e _exithandle() from exit+18 _setjmp(0xbfffe628) from _exithandle+100 _cleanup() from _exithandle+151 fflush(0x0) from _cleanup+9Note that even with symbols enabled, the reporting of some addresses (like the caller of fopen) is still just a hexadecimal value. This is because the only names available to the reporting code are those exported from the executable and shared libraries and by default only the necessary few global names are exported by the linker in the executable. If you use pass the -Wl,-Bexport option to the linker (see above regarding exported names) all global functions are exported.
$ LD_TRACE=sym,ret ./a.out atexit(0x80483b4) from 0x8048459 => atexit returned 0 atexit(0xbff9b09c) from 0x8048465 => atexit returned 0 atexit(0x8048514) from 0x804846f => atexit returned 0 __fpstart() from 0x804847b => __fpstart returned fopen("/etc/fstab","r") from 0x80484b1 _findiop() from _realfopen+7 => _findiop returned 0x80496d0 _open("/etc/fstab",0x0,0x1b6) from endopen+141 __thr_errno() from _cerror+29 => __thr_errno returned 0xbfffedd0 => _open returned -1 => fopen returned 0x0 fprintf(0x80495ec,"*** cannot open file"...,0x0,0x8047cb8,0x8048485) from 0x80484cc _findbuf(0x80495ec) from fprintf+116 => _findbuf returned 0x80495ec _xflsbuf(0x8047c44) from _idoprnt+358 _write(2,0x8047c04,21) from _xflsbuf+89 *** cannot open file => _write returned 21 => _xflsbuf returned 0 => fprintf returned 21 fclose(0x0) from 0x80484d7 => fclose returned -1 exit(-1) from 0x804848e _exithandle() from exit+18 _setjmp(0xbfffe628) from _exithandle+100 _cleanup() from _exithandle+151 fflush(0x0) from _cleanup+9 => fflush returned 0 => _cleanup returned => _exithandle returnedNote in this example that the return from setjmp is not displayed. Certain special functions like setjmp are sensitive to their return address. Finally, a stack trace for write results in the following:
$ LD_TRACE=sym LD_TRACE_STACK=_write ./a.out [0] _write(2,0x8047bec,21) [1] _xflsbuf+89(0x8047c2c) [0xbffa7b05] [2] _idoprnt+358(0x8047c2c,0x80484f8,0x8047c88) [0xbffa1eb6] [3] fprintf+201(0x80495ec,"*** cannot open file"...,0x0,0x8047ca0,0x8048485) [0xbffa8195] [4] 0x80484cc(0x1,0x8047cac,0x8047cb4) Page 41 SCO OpenServer 6 [5] 0x80484cc(0x8047cac,0x8047cb4,0x0) *** cannot open file1.9.3 Memory debugging with memtool
C (and to some degree C++) programs are infamous for memory allocation/corruption problems that are difficult to debug. These can sometimes show up during ports of "working" code because a malloc/free mistake might be missed on one platform but not on another. Such problems can go undetected for some time. Commercial tools such as Purify can help track down such problems.
The Dev Sys has a similar tool created by SCO, called memtool. Consider this simple error-ridden program:
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string.h> 4 5 int main() { 6 char *p = malloc(7), *q = "yes, too long\n"; 7 strcpy(p, q); 8 free(p); 9 q = 0; 10 *p = `Y'; 11 realloc(p, 3); 12 fputs(p, stderr); 13 return *q; 14 }Most of the time, this program will run without problems, but will occassionally fail with memory allocation errors. memtool can be used to pinpoint the code in your application that may cause memory-allocation-related problems. If you take the same program as above and recompile it with -g for maximum symbolic information, you can then run the executable using memtool. This produces the following diagnostic output:
$ cc -g error.c $ /usr/ccs/bin/memtool ./a.out ============================================================================== Some abuses or potential misuses of the dynamic memory allocation subsystem have been detected. The following multiline diagnostics are descriptions of what exactly has been seen. They may include use of terms and concepts with which you may be unfamiliar. Use the "-v" option to get the complete version of this introduction. ============================================================================== A block's spare bytes have been modified. This usually occurs due to writing beyond the block's regular bytes, either because an insufficient number of bytes were requested when the block was allocated or simply due to a programming logic error. History for block at address 0x8049b70: *Stack trace when detected: [0] free(ptr=0x8049b70) [1] main(0x1,0x8047e24,0x8047e2c) [error.c@8] in ./a.out [2] _start() [0x80485f4] in ./a.out *Stack trace when block at 0x8049b70 was allocated: [0] malloc(sz=7) [1] main() [error.c@6] in ./a.out [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out Annotated snapshot surrounding the live allocation at address 0x8049b70 when the 5 bytes [0x8049b77,0x8049b7b] were found to have been modified. This allocation holds 7 byte(s) followed by 5 extra (or spare) byte(s), and, in this case, spare bytes were found to have been modified. 0x8049b60: 0x00000000 0x00000000 0x00000000 0x00000011 ................ : ******** **** 0x8049b70: 0x2c736579 0x6f6f7420 0x6e6f6c20 0x00000a67 yes, too long... : -------- ^^------ ^^^^^^^^ -------^^^^^ ============================================================================== A block's header has been modified. Often this occurs due to mistakenly writing past the end of the preceding block. You might also try using the "-x" option to add spare bytes to the end of each block, and see whether your application behaves differently. History for block at address 0x8049b80: *Stack trace when detected: [0] free(ptr=0x8049b70) [1] main(0x1,0x8047e24,0x8047e2c) [error.c@8] in ./a.out [2] _start() [0x80485f4] in ./a.out Annotated snapshot surrounding the live allocation at address 0x8049b80 when the 4 bytes [0x8049b7c,0x8049b7f] were found to have been modified. This allocation holds 4 bytes, but, in this case, the allocation's header was found to have been modified. 0x8049b70: 0x2c736579 0xca6f7420 0xcacacaca 0x00000a67 yes, to.....g... : ^^^^^^^^ ^^^^ 0x8049b80: 0x00000000 0x00000015 0xcacacaca 0xcacacaca ................ : -------- ---- ============================================================================== A recently free()d block was passed as the first argument to realloc(). Only null pointers or live block addresses are permitted to be passed to realloc(), although, in this implementation, were dynamic memory checking not enabled, this block's contents would have been preserved between its being freed and this call to realloc(), but this is a nonportable feature of this implementation which should not be relied on. History for block at address 0x8049b70: *Stack trace when detected: [0] realloc(ptr=0x8049b70,sz=3) [1] main(0x1,0x8047e24,0x8047e2c) [error.c@11] in ./a.out [2] _start() [0x80485f4] in ./a.out *Stack trace when block at 0x8049b70 was released: [0] free(ptr=0x8049b70) [1] main() [error.c@8] in ./a.out [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out *Stack trace when block at 0x8049b70 was allocated: [0] malloc(sz=7) [1] main() [error.c@6] in ./a.out [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out ============================================================================== A free()d block has been modified. This usually means that the block was passed to free() or realloc(), but the block continued to be used by your application, possibly far removed from the deallocating code. History for block at address 0x8049b70: *Stack trace when detected: [0] realloc(ptr=0x8049b70,sz=3) [1] main(0x1,0x8047e24,0x8047e2c) [error.c@11] in ./a.out [2] _start() [0x80485f4] in ./a.out *Stack trace when block at 0x8049b70 was released: [0] free(ptr=0x8049b70) [1] main() [error.c@8] in ./a.out [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out *Stack trace when block at 0x8049b70 was allocated: [0] malloc(sz=7) [1] main() [error.c@6] in ./a.out [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out Annotated snapshot surrounding the free allocation at address 0x8049b70 when the byte at 0x8049b70 was found to have been modified. This allocation holds 12 bytes, one of which was found to have been modified. 0x8049b60: 0x00000000 0x00000000 0x00000000 0x00000011 ................ : ******** **** 0x8049b70: 0xcacaca59 0xcacacaca 0xcacacaca 0x00000179 Y...........y... : ------^^ -------- -------- ^----------- ============================================================================== LIVE ALLOCATIONS AT PROCESS EXIT ============================================================================== Memory allocations that have not been released by the time your process is finished are in no way an error, but they are potentially ``leaks'' -- allocations that inadvertently have not been released once they were no longer needed or in use. If your application has more than a few live allocations displayed below with the same size and/or were allocated at the same location, you may well have a leak; or if your application, when run with more data or for longer periods, displays more live allocations here, you also may have a leak. A leak also need not be repaired: A short-lived process can easily survive having many leaks, as long as they are not too large and there are not so many that available memory resources could become exhausted (or even strained). Moreover, it may well be that ``the leaks'' are allocations that were all in use up to just before the process exits, and the effort and the expense to release them all is not warranted. Stack trace for 4 byte block at 0x8049cf8: [0] realloc(ptr=0x8049b70,sz=3) [1] main() [error.c@11] in ./a.out [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out *Stack trace for block previously at 0x8049b70 before realloc() to 0x8049cf8: [0] free(ptr=0x8049b70) [1] main() [error.c@8] in ./a.out [2] _start(presumed:0x1,0x8047e24,0x8047e2c) [0x80485f9] in ./a.out1.9.4 Source debugging with debug
The Dev Sys debugger, debug, is a powerful tool for source and assembly-level debugging. It supports both C and C++ language debugging. (For Java debugging, use the command-line jdb debugger.) The debugger has two basic user interfaces: command line and graphical.
Debugging the port of an existing application can be different from program development. Some debugger features that may be useful in this regard are:
- The map command is excellent at showing the layout of memory, and where any arbitrary address might be.
- Multithreaded debugging and multiprocess debugging support is strong in the debugger. Many commands take a -p process-nbr.thread-nbr argument indicating a specific process or thread, with -p all applying to all processes or threads.
- You can follow program forks into both the parent and child processes; other debuggers only allow one or the other.
- The debugger allows you to grab existing processes (for example, that are hung in loops) or debug core dumps.
The debug tool is not related to the dbx and gdb debuggers many Release 5 users are familiar with, and uses a different command syntax. However, there is "A Guide to debug for dbx Users" on page 63 that will help such users gain familiarity with debug.
For more information on the Dev Sys debugger, see the Dev Sys debug documentation, on the web at http://osr600doc.sco.com/en/SDK_cdebug/CONTENTS.html">http://osr600doc.sco.com/en/SDK_cdebug/CONTENTS.html.
1.10 Development System documentation
See the SCO OpenServer 6 Development System Documentation on the web at http://osr600doc.sco.com/en/Navpages/SDKhome.html. If you installed the Development System on your OpenServer 6 system, the documentation is also available locally at http://hostname:8457/en/Navpages/SDKhome.html, where hostname is the name of your system or localhost.