United States |
Previous | Contents | Index |
If the linker detects any errors while linking object modules, it displays messages indicating the cause and severity of the error. If any error or fatal error conditions occur (that is, errors with severities of E or F), the linker does not produce an image file.
The messages produced by the linker are descriptive, and you do not usually need additional information to determine the specific error. Some common errors that occur during linking are as follows:
$ LINK OCEAN, REEF, SHELLS |
%LINK-W-NUDFSYMS, 1 undefined symbol %LINK-I-UDFSYMS, SEAWEED %LINK-W-USEUNDEF, module "OCEAN" references undefined symbol "SEAWEED" %LINK-W-DIAGISUED, completed but with diagnostics |
If an error occurs when you link modules, you can often correct it by reentering the command and specifying the correct modules or libraries. If an error indicates that a program module cannot be located, you may be linking the program with the wrong RTL.
For a complete list of linker messages, see the OpenVMS System Messages and Recovery Procedures Reference Manual.
1.5 Running a Compaq C Program
After you link your program, you can use the DCL command RUN to execute it. The RUN command has the following format:
RUN [/[NO]DEBUG] file-spec [/[NO]DEBUG] |
/[NO]DEBUG
An optional qualifier. Specify the /DEBUG qualifier to invoke the debugger if the image was not linked with it. You cannot use /DEBUG on images linked with the /NOTRACEBACK qualifier. If the image was linked with the /DEBUG qualifier and you do not want the debugger to prompt you, use the /NODEBUG qualifier. The default action depends on whether the file was linked with the /DEBUG qualifier.file-spec
The file you want to run.
The execution of a program begins at the function whose identifier is main , or, if there is no function with this identifier, at the first function seen by the VMS linker.
Unexpected results might occur if you don't have a function called main . |
The following example executes the image SAMPLE.EXE without invoking the debugger:
$ RUN SAMPLE/NODEBUG |
For more information on debugging programs, see Section C.1.
During execution, an image can generate a fatal error called an exception condition. When an exception condition occurs, the system displays an error message. Run-time errors can also be issued by the operating system or by utilities.
When an error occurs during the execution of a program, the program is terminated and the OpenVMS condition handler displays one or more messages on the currently defined SYS$ERROR device.
A message is followed by a traceback. For each module in the image that has traceback information, the condition handler lists the modules that were active when the error occurred, which shows the sequence in which the modules were called.
For example, if an integer divide-by-zero condition occurs, a run-time message like the following appears:
%SYSTEM-F-INTDIV, arithmetic trap, integer divide by zero at PC=00000FC3, PSL=03C00002 |
This message is followed by a traceback message similar to the following:
%TRACE-F-TRACEBACK, symbolic stack dump follows module name routine name line rel PC abs PC A C 8 00000007 00000FC3 B main 1408 000002F7 00000B17 |
The information in the traceback message follows:
module name
The name or names of an image module that was active when the error occurred.The first module name is that of the module in which the error occurred. Each subsequent line gives the name of the caller of the module named on the previous line. In this example, the modules are A and B; main called C.
routine name
The name of the function in the calling sequence.line
The compiler-generated line number of the statement in the source program where the error occurred, or at which the call or reference to the next procedure was made. Line numbers in these messages match those in the listing file (not the source file).rel PC
The value of the PC (program counter). This value represents the location in the program image at which the error occurred or at which a procedure was called. The location is relative to the virtual memory address that the linker assigned to the code program section of the module indicated by module name.abs PC
The value of the PC in absolute terms; that is, the actual address in virtual memory representing the location at which the error occurred.
Traceback information is available at run time only for modules
compiled and linked with the traceback option in effect. The traceback
option is in effect by default for both the CC and LINK commands. You
may use the CC command qualifier /NODEBUG and the LINK command
qualifier /NOTRACEBACK to exclude
traceback information. However, traceback information should be
excluded only from thoroughly debugged program modules.
1.6 Passing Arguments to the main Function
The main function in a Compaq C program can accept arguments from the command line from which it was invoked. The syntax for a main function is:
int main(int argc, char *argv[ ], char *envp[ ]) {...} |
argc
The number of arguments in the command line that invoked the program.argv
A pointer to an array of character strings that contain the arguments.envp
The environment array. It contains process information such as the user name and controlling terminal. It has no bearing on passing command-line arguments. Its primary use in Compaq C programs is during exec and getenv function calls. (For more information, see the Compaq C Run-Time Library Reference Manual for OpenVMS Systems).
In the main function definition, the parameters are optional. However, you can access only the parameters that you define. You can define the main function in any of the following ways:
int main() int main(int argc) int main(int argc, char *argv[ ]) int main(int argc, char *argv[ ], char *envp[ ]) |
To pass arguments to the main function, you must install the program as a DCL foreign command. When a program is installed and run as a foreign command, the argc parameter is always greater than or equal to 1, and argv[0]always contains the name of the image file.
The procedure for installing a foreign command involves using a DCL assignment statement to assign the name of the image file to a symbol that is later used to invoke the image. For example:
$ ECHO == "$DSK$:COMMARG.EXE"[Return] |
The symbol ECHO is installed as a foreign command that invokes the image in COMMARG.EXE. The definition of ECHO must begin with a dollar sign ($) and include a device name, as shown.
For more information about the procedure for installing a foreign command, see the OpenVMS DCL Dictionary.
Example 1-1 shows a program called COMMARG.C, which displays the command-line arguments that were used to invoke it.
Example 1-1 Echo Program Using Command-Line Arguments |
---|
/* This program echoes the command-line arguments. */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i; /* argv[0] is program name */ printf("program: %s\n",argv[0]); for (i = 1; i < argc; i++) printf("argument %d: %s\n", i, argv[i]); exit (EXIT_SUCCESS); } |
You can compile and link the program using the following DCL command lines:
$ CC COMMARG[Return] $ LINK COMMARG[Return] |
A sample output for Example 1-1 follows:
$ ECHO Long "Day's" "Journey into Night"[Return] program: db7:[oneill.plays]commarg.exe;1 argument 1: long argument 2: Day's argument 3: Journey into Night |
DCL converts most arguments on the command line to uppercase letters.
Compaq C internally parses and modifies the altered command line
to make Compaq C argument access compatible with C programs
developed on other systems. All alphabetic arguments in the command
line are delimited by spaces or tabs. Arguments with embedded spaces or
tabs must be enclosed in quotation marks (" "). Uppercase
characters in arguments are converted to lowercase, but arguments
within quotation marks are left unchanged.
1.7 64-bit Addressing Support (ALPHA ONLY)
OpenVMS Alpha 64-bit virtual addressing support makes the 64-bit virtual address space defined by the Alpha architecture available to the OpenVMS operating system and its users. It also allows per-process virtual addressing for accessing dynamically mapped data beyond traditional 32-bit limits.
This support is provided through command-line qualifiers and pragma preprocessor directives that control the size of the C pointer because:
Single objects larger than 2 gigabytes are not fully supported, even with 64-bit virtual addressing in effect. |
No changes are required for existing 32-bit applications that do not
need to exploit 64-bit addressing.
1.7.1 Qualifiers and Pragmas
The following qualifiers, pragmas, and predefined macro control pointer size:
The /POINTER_SIZE qualifier lets you specify a value of 64 or 32 (or LONG or SHORT) as the default pointer size within the compilation unit. You can compile one set of modules using 32-bit pointers and another set using 64-bit pointers. Take care when these two separate groups of modules call each other.
The default is /NOPOINTER_SIZE, which:
This default represents no change over previous versions of Compaq C.
Specifying /POINTER_SIZE with a keyword value (32, 64, SHORT, or LONG) has the following effects:
Use of the /POINTER_SIZE qualifier also influences the processing of Compaq C RTL header files:
See the Compaq C Run-Time Library Reference Manual for OpenVMS Systems for more information on the impact of 64-bit pointer support on Compaq C RTL functions.
See Section 1.3.4 for more information about /POINTER_SIZE.
1.7.1.2 The __INITIAL_POINTER_SIZE Macro
The __INITIAL_POINTER_SIZE preprocessor macro is useful for header-file authors to determine:
Header-file code can then be conditionalized using the following preprocessor directives:
#if defined (__INITIAL_POINTER_SIZE) /* Compiler supports 64-bit pointers */ #if __INITIAL_POINTER_SIZE > 0 /* Application uses 64-bit pointers */ #if __INITIAL_POINTER_SIZE == 32 /* Application uses some 64-bit pointers, but default RTL routines are 32-bit.*/ #if __INITIAL_POINTER_SIZE == 64 /* Application uses 64-bit pointers and default RTL routines are 64-bit. */ |
Use the /CHECK=POINTER_SIZE qualifier to generate code that checks 64-bit pointer values at runtime to make sure they can fit in a 32-bit pointer. If such a value cannot be represented by a 32-bit pointer, the run-time code signals a range error (SS$_RANGEERR).
Be aware that the compiler generates the same kinds of warning messages for pointer-size mismatches whether or not this qualifier is specified. The run-time checks can detect problems that cannot be detected at compile time, and can help determine whether or not certain warnings are safe to suppress.
See Section 1.3.4 for more information about /CHECK=POINTER_SIZE,
including defaults and an example.
1.7.1.4 Pragmas
The #pragma pointer_size and #pragma required_pointer_size preprocessor directives can be used to change the pointer size currently in effect within a compilation unit. You can default pointers to 32-bits and then declare specific pointers within the module as 64-bits. In this case, you also need to specifically call the _malloc64 form of malloc to obtain memory from the 64-bit memory area.
These pragmas have the following format:
#pragma pointer_size keyword #pragma required_pointer_size keyword |
The keyword is one of the following:
{ short |32} | 32-bit pointer |
{ long |64} | 64-bit pointer |
save | Saves the current pointer size |
restore | Restores the current pointer size to its last saved state |
The #pragma pointer_size and #pragma required_pointer_size directives work essentially the same way, except that #pragma required_pointer_size always takes effect regardless of command-line qualifiers, while #pragma pointer_size is only in effect when the /POINTER_SIZE command-line qualifier is used.
The #pragma pointer_size behavior allows a program to be built using 64-bit features as purely as a 32-bit program, just by changing the command-line qualifier.
The #pragma required_pointer_size is intended for use in header files where interfaces to system data structures must use a specific pointer size regardless of how the program is compiled.
See Sections 5.4.17 and 5.4.18 for more information on
the pointer-size pragmas.
1.7.2 Determining Pointer Size
The pointer-size qualifiers and pragmas affect only a limited number of constructs in the C language itself. At places where the syntax creates a pointer type, the pointer-size context determines the size of that type. Pointer-size context is defined by the most recent pragma (or command-line qualifier) affecting pointer size.
Here are examples of places in the syntax where a pointer type is created:
int **p; // Declaration ip = (int **)i; // Cast |
void foo(int ia[10][20]) {} // Means the following: void foo(int (*ia)[20]) {} |
void foo (int func()): // Means the following: void foo (int (*)() func); |
typedef int a_type[10]; void foo (a_type ia); // Means the following: void foo (int *ia); |
Note that a typedef binds the meaning of pointer syntax while a macro does not. Even though both constructs can contain a * used in a declaration, the * in the macro definition is not affected by any pointer-size controls until the point at which the macro is expanded. For example:
#pragma pointer_size 64 typedef int * j_ptr; // * is 64-bit #define J_PTR int * // * is not analyzed #pragma pointer_size 32 j_ptr j; // j is a 64-bit pointer. J_PTR J; // J is a 32-bit pointer. |
The following special cases are not affected by pointer-size context:
#pragma pointer_size 64 main(int argc, char **argv) { ASSERT(sizeof(argv[0]) == 4); } |
#pragma pointer_size 64 ASSERT(sizeof("x" + 0) == 4); |
sizeof(&foo) == 32 sizeof(&s ->next) == sizeof(s) |
#pragma pointer_size 64 typedef int * ip64; #pragma pointer_size 32 typedef int * ip32; ip64 a,b; ip32 c; a = (ip32)b; // No high-order bits are lost c = (ip32)b; // High-order bits are lost |
Previous | Next | Contents | Index |
|