head 3.1; access; symbols; locks; strict; comment @.\" @; 3.1 date 95.07.09.11.28.20; author grog; state Exp; branches; next 3.0; 3.0 date 95.06.25.14.33.59; author grog; state Exp; branches; next 1.6; 1.6 date 95.06.25.10.37.56; author grog; state Exp; branches; next 1.5; 1.5 date 95.06.22.10.20.08; author grog; state Exp; branches; next 1.4; 1.4 date 95.06.09.04.31.01; author grog; state Exp; branches; next 1.3; 1.3 date 95.05.17.06.00.34; author grog; state Exp; branches; next 1.2; 1.2 date 95.02.14.11.28.58; author grog; state Exp; branches; next 1.1; 1.1 date 95.01.24.17.18.09; author grog; state Exp; branches; next ; desc @Review @ 3.1 log @Minor mods @ text @.\" For emacs, this file is in -*- nroff-fill -*- mode .\" $Id: compiling.ms,v 3.0 1995年06月25日 14:33:59 grog Exp grog $ .\" $Log: compiling.ms,v $ .\" Revision 3.0 1995年06月25日 14:33:59 grog .\" Final draft .\" .\" Revision 1.5 1995年06月22日 10:20:08 grog .\" Final draft, first cut. .\" .\" Revision 1.4 1995年06月09日 04:31:01 grog .\" Remove date from page headers .\" Minor mods .\" .\" Revision 1.3 1995年05月17日 06:00:34 grog .\" Major mods after Andy's final draft review .\" .\" Revision 1.2 1995年02月14日 11:28:58 grog .\" Minor mods .\" .\" Revision 1.1 1995年01月24日 17:18:09 grog .\" Initial revision .\" .\" Revision 1.1 1995年01月23日 09:27:18 grog .\" Initial revision .\" .\" .so global.ms .Se \*[nchcompiling] "Running the compiler" .St "Running the compiler" In the previous chapter, we looked at building from the viewpoint of \fImake\fR. The other central program in the build process is the compiler, which in UNIX is almost always a C compiler. Like \fImake\fR, the compiler can discover a surprising number of problems in what ostensibly debugged source code. In this chapter, we'll look at these problems and how to solve them. In \*[chcompile] we'll look at how the compiler works and how the various flavours of C differ. Although we restrict our attention to the C compiler, much of what we discuss relates to other compilers as well, particularly of course to C++. This chapter expects a certain understanding of the C language, of course, but don't be put of if you're still a beginner: this is more about living with C than writing it. .LP Information from the compiler can come in a number of forms: .Ls B .Li The compiler may issue \fIwarnings\fR, which are informational messages intended to draw attention to possible program errors. Their reliability and their value varies significantly: some are a sure-fire indication that something is wrong, while others should be taken with a pinch of salt. .Li The compiler may issue \fIerror\fR messages, indicating its conviction that it cannot produce a valid output module. This also usually means that the compiler will not create any output files, though you can't always rely on this. .Li The compiler may fail completely, either because of an internal bug or because it realizes that it no longer understands the input sufficiently to continue. .Le .Ah "Compiler warnings" .XX "C, compiler warnings" It's easy to make mistakes when writing programs, but it used to be even easier: nowadays, even the worst compilers attempt to catch dubious constructs and warn you about them. In this section, we'll look at what they can and can't do. .LP .XX "lint, program" Before compilers worried about coding quality, the program \fIlint\fR performed this task. \fIlint\fR is still around, but hardly anybody uses it any more, since it doesn't always match the compiler being used. This is a pity, because \fIlint\fR can catch a number of dubious situations that evade most compilers. .LP Modern compilers can recognize two kinds of potential problems: .Ls B .Li Problems related to dubious program text, like .Ps if (a = 1) return; .Pe .IP The first line of this example is almost superfluous: if I allocate the value \s10\f(CW1\fR\s0 to \s10\f(CWa\fR\s0, I don't need an \s10\f(CWif\fR\s0 to tell me what the result will be. This is probably a typo, and the text should have been .Ps if (a == 1) return; .Pe .Li Problems related to program flow. These are detected by the flow analysis pass of the optimizer. For example: .Ps int a; b = a; .Pe .IP The second line uses the value of \s10\f(CWa\fR\s0 before it has been assigned a value. The optimizer notices this omission and may print a warning. .Le In the following sections, we'll examine typical warning messages, how they are detected and how reliable they are. I'll base the sections on the warning messages from the GNU C compiler, since the it has a particularly large choice of warning messages, and since it is also widely used. Other compilers will warn about the same kind of problems, but the messages may be different. .Ref t \& n 1 gives an overview of the warnings we'll see. .Ts "Overview of warning messages" .TS H linesize(2), tab(#) ; lf(I) | lf(R)r . Kind of warning#page _ Changing non-volatile automatic variables#\*[Changing-non-volatile-automatic-variables] Character subscripts to arrays#\*[Character-subscripts-to-arrays] Dequalifying types#\*[Dequalifying-types] Functions with embedded extern definitions#\*[Functions-with-embedded-extern-definitions] Implicit conversions between enums#\*[Implicit-conversions-between-enums] Implicit return type#\*[Implicit-return-type] Incomplete switch statements#\*[Incomplete-switch-statements] Inconsistent function returns#\*[Inconsistent-function-returns] Increasing alignment requirements#\*[Increasing-alignment-requirements] Invalid keyword sequences in declarations#\*[Invalid-keyword-sequences-in-declarations] Long indices for switch#\*[long-indices-for-switch] Missing parentheses#\*[Missing-parentheses] Nested comments#\*[Nested-comments] Signed comparisons of unsigned values#\*[Signed-comparisons-of-unsigned-values] Trigraphs#\*[Trigraphs] Uninitialized variables#\*[Uninitialized-variables] .TH N .TE .Te .Bh "Implicit return type" .Pn Implicit-return-type .XX "C, warning, implicit return type" K&R C allowed programs like .Ps main () { printf ("Hello, World!\en"); } .Pe ANSI C has two problems with this program: .Ls B .Li The function name \s10\f(CWmain\fR\s0 does not specify a return type. It defaults to \s10\f(CWint\fR\s0. .Li Since \s10\f(CWmain\fR\s0 is implicitly an \s10\f(CWint\fR\s0 function, it should return a value. This one does not. .Le Both of these situations can be caught by specifying the \s10\f(CW-Wreturn-type\fR\s0 option to \fIgcc\fR. This causes the following messages: .XX "C, gcc, -Wreturn-type option" .Ps $ \f(CBgcc -c hello.c -Wreturn-type\f(CW hello.c:2: warning: return-type defaults to `int' hello.c: In function `main': hello.c:4: warning: control reaches end of non-void function .Pe .Bh "Inconsistent function returns" .Pn Inconsistent-function-returns .XX "C, warning, inconsistent function returns" The following function does not always return a defined value: .Ps foo (int x) { if (x> 3) return x - 1; } .Pe If \s10\f(CWx\fR\s0 is greater than 3, this function returns \s10\f(CWx - 1\fR\s0. Otherwise it returns with some uninitialized value, since there is no explicit \s10\f(CWreturn\fR\s0 statement for this case. This problem is particularly insidious, since the return value will be the same for every invocation on a particular architecture (possibly the value of \s10\f(CWx\fR\s0), but this is a by-product of the way the compiler works, and may be completely different if you compile it with a different compiler or on some other architecture. .Bh "Uninitialized variables" .Pn Uninitialized-variables .XX "C, warning, uninitialized variables" Consider the following code: .Ps void foo (int x) { int a; if (x> 5) a = x - 3; bar (a); \fI... etc\fR .Pe Depending on the value of \s10\f(CWx\fR\s0, \s10\f(CWa\fR\s0 may or may not be initialized when you call \s10\f(CWbar\fR\s0. If you select the \f(CW-Wuninitialized\fR\s0 compiler option, it warns you when this situation occurs. Some compilers, including current versions of \fIgcc\fR place some limitations on this test. .XX "C, gcc, -Wuninitialized option" .Bh "Signed comparisons of unsigned values" .Pn Signed-comparisons-of-unsigned-values .XX "C, warning, signed comparisons" Occasionally you see code of the form .Ps int foo (unsigned x) { if (x>= 0) \fI\&... etc\fR .Pe Since \s10\f(CWx\fR\s0 is unsigned, its value is \fIalways\fR>= 0, so the \s10\f(CWif\fR\s0 is superfluous. This kind of problem is surprisingly common: system header files may differ in opinion as to whether a value is signed or unsigned. The option \s10\f(CW-W\fR\s0 causes the compiler to issue warnings for this and a whole lot of other situations. .Bh "Character subscripts to arrays" .Pn Character-subscripts-to-arrays .XX "C, warning, character subscripts" Frequently, the subscript to an array is a character. Consider the following code: .Ps char iso_translate [256] = /* translate table for ISO 8859-1 to LaserJet */ { \fI\& codes for the first 160 characters\f(CW 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, \fI\&... etc\f(CW }; #define xlate(x) iso_translate [x]; char *s; /* pointer in buf */ for (*s = buf; *s; s++) *s = xlate (*s); .Pe The intention of \s10\f(CWxlate\fR\s0 is to translate text to a form used by older model HP LaserJet printers. This code works only if the \s10\f(CWchar *s\fR\s0 is unsigned. By default, the C \s10\f(CWchar\fR\s0 type is a signed value, and so the characters \s10\f(CW0x80\fR\s0 to \s10\f(CW0xff\fR\s0 represent a negative array offset, and the program attempts (maybe successfully) to access a byte outside the table \s10\f(CWiso_translate\fR\s0. \fIgcc\fR warns about this if you set the option \f(CW-Wchar-subscripts\fR\s0. .XX "C, gcc, -Wchar-subscripts option" .Bh "Dequalifying types" .Pn Dequalifying-types .XX "C, warning, dequalifying types" The following code fragment can cause problems: .Ps char *profane; void foo (const char *holy) { profane = holy; .Pe The assignment of \s10\f(CWholy\fR\s0 to \s10\f(CWprofane\fR\s0 loses the qualifier \s10\f(CWconst\fR\s0, and the compiler complains about the fact. On the other hand, this is valid: .Ps profane = (char *) holy; .Pe This doesn't make it a better idea: \s10\f(CWholy\fR\s0 is supposed to be unchangeable, and here you are removing this qualifier. If you specify the \s10\f(CW-Wcast-qual\fR\s0 option to \fIgcc\fR, it complains if you use a cast to remove a type qualifier such as \s10\fIconst\fR\s0. .XX "C, gcc, -Wcast-qual option" .XX "C, const type qualifier" .Bh "Increasing alignment requirements" .Pn Increasing-alignment-requirements .XX "C, warning, increasing alignment requirements" Many processors require that specific data types be aligned on specific boundaries, and the results can be spectacular if they are not--see \*[chhard], page \*[wordalign], for more details. We can easily outsmart the C compiler with code like: .Ps void foo (char *x) { int *ip = (int *) x; .Pe In this case, there is a good chance that the \s10\f(CWint *\fR\s0 pointer \s10\f(CWip\fR\s0 requires a specific alignment and is not allowed to point at any address in memory the way the \s10\f(CWchar\fR\s0 pointer \s10\f(CWx\fR\s0 is allowed to do. If you specify the \s10\f(CW-Wcast-align\fR\s0 option to \fIgcc\fR, it warns you of such assignments. .XX "C, gcc, -Wcast-align option" .Bh "Implicit conversions between enums" .Pn Implicit-conversions-between-enums .XX "C, warning, implicit conversions" .XX "C, enum type" .XX "C, gcc, -Wenum-clash option" One of the advantages of \fIenums\fR is that they make type checking easier--we'll look at that in more detail in \*[chcompiler], page \*[enums]. If you specify the \s10\f(CW-Wenum-clash\fR\s0 option to \fIgcc\fR, \fIand\fR you're compiling C++, it warns about sloppy use of \fIenum\fRs. .Bh "Incomplete switch statements" .Pn Incomplete-switch-statements .XX "C, warning, incomplete switch statements" .XX "C, switch statement" .XX "C, case label" .XX "C, gcc, -Wswitch option" A frequent cause of error in a \s10\fIswitch\fR\s0 statement is that the index variable (the variable that decides which case is chosen) may assume a value for which no \s10\fIcase\fR\s0 has been specified. If the index variable is an \s10\f(CWint\fR\s0 of some kind, there is not much you can do except include a \s10\f(CWdefault\fR\s0 clause. If the index variable is an \s10\f(CWenum\fR\s0, the compiler can check that \s10\f(CWcase\fR\s0 clauses exist for all the possible values of the variable, and warns if they do not. It also warns if \s10\f(CWcase\fR\s0 clauses exist for values that are not defined for the type of the index variable. Specify the \s10\f(CW-Wswitch\fR\s0 option for these warnings. .Bh "long indices for switch" .Pn long-indices-for-switch .XX "C, warning, long indices for switch" In some dialects of pre-ANSI C, you could write things like .Ps foo (x) long x; { switch (x) { \fI\&... etc\fR .Pe .XX "C, gcc, -traditional option" This is no longer allowed in ANSI C: indices for \s10\f(CWswitch\fR\s0 must evaluate to an \s10\f(CWint\fR\s0, even if \s10\f(CWint\fR\s0 and \s10\f(CWlong\fR\s0 have the same length. \fIgcc\fR issues a warning about \s10\f(CWlong\fR\s0 indices in \s10\f(CWswitch\fR\s0 unless you specify the \s10\f(CW-traditional\fR\s0 option. .Bh "Changing non-volatile automatic variables" .Pn Changing-non-volatile-automatic-variables .XX "C, warning, changing non-volatile automatic variables" .XX "C, volatile type qualifier" .XX "setjmp, function" Under certain circumstances, a signal handler might modify a local automatic variable if the function has called \s10\f(CWsetjmp\fR\s0--see \*[chsignal], page \*[longjmp-volatile] for more details. \fIgcc\fR options this situation as a warning if you specify the \s10\f(CW-W\fR\s0 option. This is a complicated problem: .Ls B .Li It can occur only during an optimizing compilation, since the keyword \s10\fIvolatile\fR\s0 has meaning only in these circumstances. In addition, the situation is recognized only by the optimizer. .Li .XX "longjmp, function" The optimizer cannot recognize when a \s10\f(CWlongjmp\fR\s0 could be performed. This depends on semantics outside the scope of the optimizer. As a result, it could issue this warning when there is, in fact, no danger. .Le .Bh "Invalid keyword sequences in declarations" .Pn Invalid-keyword-sequences-in-declarations .XX "C, warning, invalid keyword sequences" Currently, it is permissible to write declarations like .Ps int static bad_usage; .Pe .XX "C, static storage class" Here the storage class specifier \s10\fIstatic\fR\s0 comes after the type specifier \s10\f(CWint\fR\s0. The ANSI Standard still permits this, but declares the usage to be obsolescent. \fIgcc\fR issues a warning when it encounters this and the option \s10\f(CW-W\fR\s0 has been set. .Bh "Trigraphs" .Pn Trigraphs .XX "C, warning, trigraphs" .XX "C, gcc, -Wtrigraphs option" Trigraphs (see \*[chcompiler], page \*[trigraphs]) are no error, at least according to the ANSI Standard. The Free Software Foundation makes no bones about their opinion of them, and so \fIgcc\fR supplies the option \s10\f(CW-Wtrigraphs\fR\s0, which prints a warning if any trigraphs occur in the source code. Since this works only if the option \s10\f(CW-trigraphs\fR\s0 is used to enable them, it is not clear that this is of any real use. .Bh "Nested comments" .Pn Nested-comments .XX "C, warning, nested comments" .Pn nested-comments Occasionally you see code like .Ps void foo (int x) { int y; /* state information y = bar (); /* initialize y */ if (y == 4) \fI\&... etc\fR .Pe The code looks reasonable, and it is syntactically correct C, but in fact the comment after the declaration of \s10\f(CWy\fR\s0 is not terminated, so it includes the whole of the next line, which is almost certainly not the intention. \fIgcc\fR recognizes this if it finds the sequence \s10\f(CW/*\fR\s0 in a comment, and warns of this situation if you specify the \s10\f(CW-Wcomment\fR\s0 option. .XX "C, gcc, -Wcomment option" .Bh "Missing parentheses" .Pn Missing-parentheses .XX "C, warning, missing parentheses" What value does the following code return? .Ps int a = 11 << 4 & 7 << 2> 4; .Pe .XX "Kernighan, Brian" .XX "Ritchie, Dennis" The result is 0, but the real question is: in what order does the compiler evaluate the expression? You can find the real answer on page 53 of K&R, but you don't want to do that all the time. We can re-write the code as .Ps int a = (11 << 4) & ((7 << 2)> 4); .Pe .XX "C, gcc, -Wparentheses option" This makes it a lot clearer what is intended. \fIgcc\fR warns about what it considers to be missing parentheses if you select the \s10\f(CW-Wparentheses\fR\s0 option. By its nature, this option is subjective, and you may find that it complains about things that look fine to you. .Bh "Functions with embedded extern definitions" .Pn Functions-with-embedded-extern-definitions .XX "C, warning, embedded extern definitions" K&R C allowed you to write things like .Ps int datafile; foo (x) { extern open (); datafile = open ("foo", 0777); } .Pe .XX "C, extern declaration" .XX "C, gcc, -traditional option" .XX "C, gcc, -Wnested-externs option" The \s10\fIextern\fR\s0 declaration was then valid until the end of the source file. In ANSI C, the scope of \s10\f(CWopen\fR\s0 would be the scope of \s10\f(CWfoo\fR\s0: outside of \s10\f(CWfoo\fR\s0, it would no longer be known. \fIgcc\fR issues a warning about \s10\f(CWextern\fR\s0 statements inside a function definition unless you supply the \s10\f(CW-traditional\fR\s0 option. If you are using \s10\f(CW-traditional\fR\s0 and want these messages, you can supply the \s10\f(CW-Wnested-externs\fR\s0 option as well. .Ah "Compiler errors" .XX "errors, C compiler" .XX "C, compiler errors" Of course, apart from warnings, you frequently see error messages from the compiler--they are the most common reason for a build to fail. In this section, we'll look at some of the more common ones. .Bh "Undefined symbols" .XX "C, error message, undefined symbols" This is one of the most frequent compiler error messages you see during porting. At first sight, it seems strange that the compiler should find undefined symbols in a program that has already been installed on another platform: if there are such primitive errors in it, how could it have worked? .LP In almost every case, you will find one of the following problems: .Ls B .Li .XX "C, #ifdef directive" The definition you need may have been \f(CW#ifdef\fR'ed out. For example, in a manually configured package, if you forget to specify a processor architecture, the package may try to compile with no processor definitions, which is sure to give rise to this kind of problem. .Li The symbol may have been defined in a header file on the system where it was developed. This header file is different on your system, and the symbol you need is never defined. .Li You may be looking at the wrong header files. Some versions of \fIgcc\fR install "fixed" copies of the system header files in their own private directory. For example, under BSD/386 version 1.1, \fIgcc\fR version 2.6.3 creates a version of \fIunistd.h\fR and hides it in a private directory. This file omits a number of definitions supplied in the BSDI version of \fIunistd.h\fR. You can confirm which header files have been included by running \fIgcc\fR with the \s10\f(CW-H\fR\s0 option. In addition, on page \*[preprocessor-output] we look at a way to check exactly what the preprocessor did. .Le .XX "link.h, header file" .XX "gdb, program" The second problem is surprisingly common, even on supposedly identical systems. For example, in most versions of UNIX System V.4.2, the system header file \fIlink.h\fR defines information and structures used by debuggers. In UnixWare 1.0, it defines information used by some Novell-specific communications protocols. If you try to compile \fIgdb\fR under UnixWare 1.0, you will have problems as a result: the system simply does not contain the definitions you need. .LP .XX "O_NDELAY" .XX "open, function" .XX "_POSIX_SOURCE" Something similar happens on newer System V systems with POSIX.1 compatibility. A program that seems formally correct may fail to compile with an undefined symbol \f(CWO_NDELAY\fR. \f(CWO_NDELAY\fR is a flag to \s10\f(CWopen\fR\s0, which specifies that the call to \s10\f(CWopen\fR\s0 should not wait for completion of the request. This can be very useful, for example, when the \s10\f(CWopen\fR\s0 is on a serial line and will not complete until an incoming call occurs. The flag is supported by almost all modern UNIX ports, but it is not defined in POSIX.1. The result is that the definition is carefully removed if you compile defining \f(CW-D_POSIX_SOURCE\fR. .LP .XX "O_NOCTTY" You might think that this isn't a problem, and that you can replace \s10\f(CWO_NDELAY\fR\s0 with the POSIX.1 flag \s10\f(CWO_NONBLOCK\fR\s0. Unfortunately, the semantics of \s10\f(CWO_NONBLOCK\fR\s0 vary from those of \s10\f(CWO_NDELAY\fR\s0: if no data is available, \s10\f(CWO_NONBLOCK\fR\s0 returns -1, and \s10\f(CWO_NDELAY\fR\s0 returns 0. You can make the change, of course, but this requires more modifications to the program, and you have a strraighforward alternative: \f(CW#undef _POSIX_SOURCE\fR. If you do this, you may find that suddenly other macros are undefined, for example \f(CWO_NOCTTY\fR. System V.4 only defines this variable if \f(CW_POSIX_SOURCE\fR is set. .LP There's no simple solution to this problem. It is caused by messy programming style: the programmer has mixed symbols defined only by POSIX.1 with those that are not defined in POSIX.1. The program may run on your current system, but may stop doing so at the next release. .Bh "Conflicts between preprocessor and compiler variables" .XX "C, conflicts between preprocessor and compiler variables" Occasionally you'll see things that seem to make absolutely no sense at all. For example, porting \fIgcc\fR, I once ran into this problem: .Ps gcc -c -DIN_GCC -g -O3 -I. -I. -I./config \e -DGCC_INCLUDE_DIR=\e"/opt/lib/gcc-lib/i386--sysv/2.6.0/include\e" \e -DGPLUSPLUS_INCLUDE_DIR=\e"/opt/lib/g++-include\e" \e -DCROSS_INCLUDE_DIR=\e"/opt/lib/gcc-lib/i386--sysv/2.6.0/sys-include\e" \e -DTOOL_INCLUDE_DIR=\e"/opt/i386--sysv/include\e" \e -DLOCAL_INCLUDE_DIR=\e"/usr/local/include\e" \e -DSTD_PROTO_DIR=\e"/opt/lib/gcc-lib/i386--sysv/2.6.0\e" \e ./protoize.c \&./protoize.c:156: macro `puts' used without args .Pe Looking at this part of \fIprotoize.c\fR, I found lots of external definitions: .Ps extern int fflush (); extern int atoi (); extern int puts (); extern int fputs (); extern int fputc (); extern int link (); extern int unlink (); .Pe Line 156 is, not surprisingly, the definition of \s10\f(CWputs\fR\s0. But this is a definition, not a call, and certainly not a macro. And why didn't it complain about all the other definitions? There were many more than shown here. .LP .XX "preprocessor output, examining" .XX "C preprocessor output, examining" .Pn preprocessor-output In cases like this, it's good to understand the way the compiler works--we'll look at this in more detail in \*[chcompiler], on page \*[cc-prog]. At the moment, we just need to recall that programs are compiled in two stages: first, the preprocessor expands all preprocessor definitions and macros, and then the compiler itself compiles the resultant output, which can look quite different. .LP If you encounter this kind of problem, there's a good chance that the compiler is not seeing what you expect it to see. You can frequently solve this kind of riddle by examining the view of the source that the compiler sees, the output of the preprocessor. In this section, we'll look at the technique I used to solve this particular problem. .LP All compilers will allow you to run the preprocessor separately from the compiler, usually by specifying the \s10\f(CW-E\fR\s0 option--see your compiler documentation for more details. In this case, I was running the compiler in an \fIxterm\fR\**, .FS \fIxterm\fR is a terminal emulator program that runs under X11. If you don't use X11, you should--for example, it makes this particular technique much easier. .FE so I was able to cut and paste the complete 8-line compiler invocation as a command to the shell, and all I needed to type was the text in bold face: .Ps $ gcc -c -DIN_GCC -g -O3 -I. -I. -I./config \e -DGCC_INCLUDE_DIR=\e"/opt/lib/gcc-lib/i386--sysv/2.6.0/include\e" \e -DGPLUSPLUS_INCLUDE_DIR=\e"/opt/lib/g++-include\e" \e -DCROSS_INCLUDE_DIR=\e"/opt/lib/gcc-lib/i386--sysv/2.6.0/sys-include\e" \e -DTOOL_INCLUDE_DIR=\e"/opt/i386--sysv/include\e" \e -DLOCAL_INCLUDE_DIR=\e"/usr/local/include\e" \e -DSTD_PROTO_DIR=\e"/opt/lib/gcc-lib/i386--sysv/2.6.0\e" \e ./protoize.c \f(CB-E -o junk.c\f(CW $ .Pe If you don't have \fIxterm\fR, you can do the same sort of thing by editing the make log (see \*[chbuild], page \*[make-log]), which will contain the invocation as well. .LP \fIjunk.c\fR starts with: .Ps # 1 "./config.h" 1 # 1 "./config/i386/xm-i386.h" 1 \fI40 empty lines\f(CW # 1 "./tm.h" 1 \fI19 empty lines\f(CW # 1 "./config/i386/gas.h" 1 \fI22 empty lines\f(CW .Pe This file seems to consist mainly of empty lines, and the lines that aren't empty don't seem to be C! In fact, the \s10\f(CW#\fR\s0 lines \fIare\fR C (see the \s10\f(CWline\fR\s0 directive in \*[chcompiler], page \*[line-directive]), except that in this case the keyword \s10\f(CWline\fR\s0 has been omitted. The empty lines are where comments and preprocessor directives used to be. The error message referred to line 156 of \fIprotoize.c\fR, so I searched for lines with \s10\f(CWprotoize.c\fR\s0 on them. I found a number of them: .Ps $ \f(CBgrep protoize.c junk.c\f(CW # 1 "./protoize.c" # 39 "./protoize.c" 2 # 59 "./protoize.c" 2 # 62 "./protoize.c" 2 # 63 "./protoize.c" 2 \fI\&... etc\f(CW # 78 "./protoize.c" 2 # 222 "./protoize.c" .Pe Clearly, the text was between lines 78 and 222. I positioned on the line \fIafter\fR the marker for line 78 and moved down (156 - 78) or 78 lines. There I found: .Ps extern int fflush (); extern int atoi (); extern int ((fputs(( ), stdout) || (( stdout )->_\/_bufp < ( stdout )->_\/_put_limit ? (int) (unsigned char) (*( stdout )->_\/_bufp++ = (unsigned char) ( '\n' )) :_\/_flshfp (( stdout ), (unsigned char) ( '\n' ))) == (-1) ) ? (-1) : 0) ; extern int fputs (); extern int fputc (); extern int link (); extern int unlink (); .Pe .XX "C, gcc, -dD option" Well, at any rate this made it clear why the compiler was complaining. But where did this junk come from? It can be difficult to figure this out. With \fIgcc\fR you can use the \s10\f(CW-dD\fR\s0 option to keep the preprocessor definitions--unfortunately, the compiler still removes the other preprocessor directives. I used \s10\f(CW-dD\fR\s0 as well, and found in \fIjunk.c\fR: .Ps # 491 "/opt/include/stdio.h" 2 \fI25 lines missing\f(CW extern int fputs (_\/_const char *_\/_s, FILE *_\/_stream) ; /* Write a string, followed by a newline, to stdout. */ extern int puts (_\/_const char *_\/_s) ; #define puts(s) ((fputs((s), stdout) || _\/_putc('\n', stdout) == EOF) ? EOF : 0) .Pe This looks strange: first it declares \s10\f(CWputs\fR\s0 as an external function, then it defines it as a macro. Looking at the original source of \fIstdio.h\fR, I found: .Ps /* Write a string, followed by a newline, to stdout. */ extern int puts _\/_P ((_\/_const char *_\/_s)); #ifdef _\/_OPTIMIZE_\/_ #define puts(s) ((fputs((s), stdout) || _\/_putc('\n', stdout) == EOF) ? EOF : 0) #endif /* Optimizing. */ .Pe No, this doesn't make sense--it's a real live bug in the header file. At the very least, the declaration of \s10\f(CWputs\ ()\fR\s0 should have been in an \s10\f(CW#else\fR\s0 clause. But that's not the real problem: it doesn't worry the preprocessor, and the compiler doesn't see it. The real problem is that \fIprotoize.c\fR is trying to do the work of the header files and define \s10\f(CWputs\fR\s0 again. There are many programs that try to out-guess header files: this kind of definition breaks them all. .LP There are at least two ways to fix this problem, both of them simple. The real question is, what is the Right Thing? System or library header files should be allowed to define macros instead of functions if they want, and an application program has no business trying to do the work of the header files, so it would make sense to fix \fIprotoize.c\fR by removing all these external definitions: apart from this problem, they're also incompatible with ANSI C, since they don't describe the parameters. In fact, I chose to remove the definition from the header file, since that way I only had to do the work once, and in any case, it's not clear that the definition really would run any faster. .LP .XX "indent, program" Preprocessor output usually looks even more illegible than this, particularly if lots of clever nested \f(CW#define\fRs have been performed. In addition, you'll frequently see references to non-existant line numbers. Here are a couple of ways to make it more legible: .Ls B .Li Use an editor to put comments around all the \s10\f(CW#line\fR\s0 directives in the preprocessor output, and then recompile. This will make it easier to find the line in the preprocessor output to which the compiler or debugger is referring; then you can use the comments to follow it back to the original source. .Li Run the preprocessor output through a program like \fIindent\fR, which improves legibility considerably. This is especially useful if you find yourself in the unenviable position of having to modify the generated sources. \fIindent\fR is not guaranteed to maintain the same number of lines, so after indenting you should recompile. .Le .Bh "Other preprocessors" .XX "C, other preprocessors" .XX "yacc, program" .XX "bison, program" .Pn other-preprocessors There are many other cases in which the source file you use is not the source file that the compiler gets. For example, \fIyacc\fR and \fIbison\fR take a grammar file and make a (more or less illegible) \fI\&.c\fR file out of it; other examples are database preprocessors like Informix ESQL, which takes C source with embedded SQL statements and converts it into a form that the C compiler can compile. The preprocessor's output is intended to be read by a compiler, not by humans. .LP All of these preprocessors use lines beginning with \f(CW#\fR to insert information about the original line numbers and source files into their output. Not all of them do it correctly: if the preprocessor inserts extra lines into the source, they can become ambiguous, and you can run into problems when using symbolic debuggers, where you normally specify code locations by line number. .Bh "Syntax errors" .XX "C, syntax errors" Syntax errors in previously functional programs usually have the same causes as undefined symbols, but they show their faces in a different way. A favourite one results from omitting \fI/usr/include/sys/types.h\fR. For example, consider \fIbar.c\fR: .Ps #include #ifdef USG #include #endif ushort num; int main (int argc, char *argv []) { num = atoi (argv [1]); printf ("First argument: %d\en", num); } .Pe If you compile this under BSD/OS, you get: .Ps $ \f(CBgcc -o bar bar.c\f(CW bar.c:6: parse error before `num' bar.c:6: warning: data definition has no type or storage class .Pe There's an error because \f(CWushort\fR hasn't been defined. The compiler expected a type specifier, so it reported a syntax error, not an undefined symbol. To fix it, you need to define the type specified--see \*[apptypes] for a list of the more common type specifiers. .Bh "Virtual memory exhausted" .XX "C, error, virtual memory exhausted" You occasionally see this message, particularly when you're using \fIgcc\fR, which has a particular hunger for memory. This may be due to unrealistically low virtual memory limits for your system--by default, some systems limit total virtual memory per process to 6 MB, but \fIgcc\fR frequently requires 16 or 20 MB of memory space, and on occasion it can use up to 32 MB for a single compilation. If your system has less than this available, increase the limit accordingly. Don't forget to ensure that you have enough swap space! Modern systems can require over 100 MB of swap space. .LP Sometimes this doesn't help. \fIgcc\fR seems to have particular difficulties with large data definitions; bit map definitions in X11 programs are the sort of things that cause problems. \fIxphoon\fR, which displays a picture of the current phase of the moon on the root window, is a good example of a \fIgcc\fR-breaker. .Bh "Compiler limits exceeded" .XX "C, error, compiler limits exceeded" .XX "C, #define directive" .XX "indent, program" Some compilers have difficulties with complicated expressions. This can cause \fIcc1\fR, the compiler itself, to fail with messages like "expression too complicated" or "out of tree space." Fixing such problems can be tricky. Straightforward code shouldn't give the compiler indigestion, but some nested \fI#define\fRs can cause remarkable increases in the complexity of expressions: in some cases, a single line can expand to over 16K of text. One way to get around the problem is to preprocess the code and then break the preprocessed code into simpler expressions. The \fIindent\fR program is invaluable here: preprocessor output is not intended to be human-readable, and most of the time it isn't. .Bh "Running compiler passes individually" .XX "C, running compiler passes individually" Typical compilers run four distinct passes to compile and link a program--see \*[chcompiler], page \*[cc-prog], for more details. Sometimes running the passes separately can be useful for debugging a compilation: .Ls B .Li If you find yourself with header files that confuse your preprocessor, you can run a different preprocessor, collect the output and feed it to your compiler. Since the output of the preprocessor is not machine-dependent, you could even do this on a different machine with different architecture, as long as you ensure that you use the correct system header files. By convention, the preprocessor output for \fIfoo.c\fR would be called \fIfoo.i\fR--see \*[chcompiler], page \*[source-suffices] for a list of intermediate file suffixes--though it usually does no harm if you call it \fIfoo.c\fR and pass it through the preprocessor again, since there should no longer be anything for the second preprocessor to do. .\" Also: Are you going to show us how to "substitute preprocessors"? .\" grog: must I? .Li If you want to report a compiler bug, it's frequently a good idea to supply the preprocessor output: the bug might be dependent on some header file conflict that doesn't exist on the system where the compiler development takes place. .Li If you suspect the compiler of generating incorrect code, you can stop compilation after the compiler pass and collect the generated assembler output. .Le .Bh "Incorrect code from compiler" .XX "C, incorrect code from compiler" Compilers sometimes generate incorrect code. Incorrect code is frequently difficult to debug because the source code looks (and might be) perfect. For example, a compiler might generate an instruction with an incorrect operand address, or it might assign two variables to a single location. About the only thing you can do here is to analyze the assembler output. .LP .XX "C, gcc, -v option" One kind of compiler bug is immediately apparent: if the code is so bad that the assembler can't assemble it, you get messages from the assembler. Unfortunately, the message doesn't usually tell you that it comes from the assembler, but the line numbers change between the compiler and the assembler. If the line number seems completely improbable, either because it is larger than the number of lines in your source file, or because it seems to have nothing to do with the context of that line, there is a chance that the assembler produced the message. There are various ways to confirm which pass of the compiler produced the message. If you're using \fIgcc\fR, the simplest one is to use the \f(CW-v\fR option for the compiler, which "announces" each pass of compilation as it starts, together with the version numbers and parameters passed to the pass. This makes it relatively easy to figure out which pass is printing the error messages. Otherwise you can run the passes individually--see \*[chcompiler], page \*[cc-prog] for more details. @ 3.0 log @Final draft @ text @d2 1 a2 1 .\" $Id: compiling.ms,v 1.5 1995年06月22日 10:20:08 grog Exp grog $ d4 3 d660 17 a676 6 lots of clever nested \f(CW#define\fRs have been performed. To make it more legible, especially if you find yourself in the unenviable position of having to modify it, you can run the preprocessor output through a program like \fIindent\fR, which improves legibility considerably. Before using \fIindent\fR, make note of the lines where the errors appeared. \fIindent\fR is not guaranteed to maintain the same number of lines. @ 1.6 log @Final draft, second cut @ text @a105 11 .\" Aggregate returns#\*[Aggregate-returns] .\" Dubious arithmetic comparisons#\*[Dubious-arithmetic-comparisons] .\" Expressions with no effect#\*[Expressions-with-no-effect] .\" Implicit declarations#\*[Implicit-declarations] .\" Incomplete function prototypes#\*[Incomplete-function-prototypes] .\" Incorrect formats for printf and scanf#\*[Incorrect-formats-for-printf-and-scanf] .\" Incorrectly initialized aggregates#\*[Incorrectly-initialized-aggregates] .\" Macro arguments in strings#\*[Macro-arguments-in-strings] .\" Missing function prototypes in headers#\*[Missing-function-prototypes-in-headers] .\" Unused variables#\*[Unused-variables] .\" Writeable strings#\*[Writeable-strings] a124 40 .\" .Bh "Expressions with no effect" .\" .Pn Expressions-with-no-effect .\" .XX "C, warning, expressions with no effect" .\" The possibility of confusion between the operators \s10\f(CW=\fR\s0 and .\" \s10\f(CW==\fR\s0 can also lead to mistakes like: .\" .Ps .\" if (x> 3) .\" a == 4; .\" .Pe .\" This is syntactically perfectly valid C code, but it doesn't do much: under .\" certain circumstances, the value of \s10\f(CWa\fR\s0 is compared with 4. And .\" nothing else. .\" .LP .\" This is almost certainly a typo: programmer had intended to write \s10\f(CWa = .\" 4\fR\s0. The \s10\f(CW-W\fR\s0 option causes a warning to be issued for this kind .\" of construct. .\" .Bh "Implicit declarations" .\" .Pn Implicit-declarations .\" .XX "C, warning, implicit declarations" .\" In ANSI C, it is good practice to declare all functions and parameters before .\" use. If you specify the \s10\f(CW-Wimplicit\fR\s0 option to \fIgcc\fR, it issues a .\" warning if a function or parameter name is used before being declared. .\" .XX "C, gcc, -Wimplicit option" .\" .Bh "Incomplete function prototypes" .\" .Pn Incomplete-function-prototypes .\" .XX "C, warning, incomplete function prototypes" .\" Some flavours of C allow "incomplete" function declarations, where the return .\" type or the types of some parameters default to \s10\f(CWint\fR\s0. If you .\" specify the \s10\f(CW-Wstrict-prototypes\fR\s0 option to \fIgcc\fR, it warns you if .\" you declare or define a function without supplying the full information about .\" parameters and return type. .\" .XX "C, gcc, -Wstrict-prototypes option" .\" .Bh "Missing function prototypes in headers" .\" .Pn Missing-function-prototypes-in-headers .\" .XX "C, warning, missing function prototypes" .\" You can be even more pedantic about function prototypes and require that there .\" should always be a function declaration in a header file before you encounter .\" the function definition. You can get \fIgcc\fR to do this, too, by specifying .\" the \s10\f(CW-Wmissing-prototypes\fR\s0 option. .\" .XX "C, gcc, -Wmissing-prototypes option" a191 12 .\" .Ls B .\" .Li .\" It works only when the optimizer is in use, since it relies on data flow .\" information computed by the optimizer. .\" .Li .\" It occurs only for variables that could be stored in registers. This excludes .\" \s10\fIvolatile\fR\s0 variables, variables whose address is used explicitly, and .\" variables with sizes other than 1, 2, 4 or 8 bytes. .\" .XX "C, volatile type qualifier" .\" .Li .\" It also excludes structures, unions and arrays. .\" .Le a206 22 .\" .Bh "Dubious arithmetic comparisons" .\" .Pn Dubious-arithmetic-comparisons .\" .XX "C, warning, dubious comparisons" .\" The statment .\" .Ps .\" if (a <= b <= c) .\" .Pe .\" is perfectly syntactically valid C. First, it compares the values of .\" \s10\f(CWa\fR\s0 and \s10\f(CWb\fR\s0. The result of this comparison (0, if .\" \s10\f(CWa\fR\s0 is greater than \s10\f(CWb\fR\s0, 1 otherwise) is compared with .\" \s10\f(CWc\fR\s0. This may be what is intended, of course, but then it would be .\" better to write it as .\" .Ps .\" if ((a <= b) <= c) .\" .Pe .\" which means the same thing. The original notation looks so much like .\" mathematical notation that the author probably intended to write: .\" .Ps .\" if ((a <= b) && (b <= c)) .\" .Pe .\" The \s10\f(CW-W\fR\s0 option causes a warning to be issued when this kind of .\" construct is encountered. a234 47 .\" .Bh "Unused variables" .\" .Pn Unused-variables .\" .XX "C, warning, unused variables" .\" As we discussed at the beginning of the section, the compiler can detect and .\" report variables that are defined but not used. Non-static global variables are .\" excluded from this test, since they are known externally and could be used by .\" other modules. Specify the \s10\f(CW-Wunused\fR\s0 option to get these warnings. .\" .XX "C, gcc, -Wunused option" .\" .LP .\" Occasionally, this can be a nuisance. For example, if you are using RCS, you .\" might have the following code: .\" .Ps .\" static char rcs_id [] .\" = "$\&Id: foo.c,v 1.6 1994/08/07 11:49:03 grog Exp grog $"; .\" .Pe .\" The compiler complains about every one of these, since nothing in the program .\" refers to it. The \fIgcc\fR documentation suggests that you can prevent this .\" warning with the following macro: .\" .Ps .\" #define USE(var) static void * use_##var = (&use_##var, (void *) &var) .\" USE (rcs_id); .\" .Pe .\" This creates a pointer to the string, which takes up space, but gets rid of the .\" warning message. It's your decision whether this is a cleaner approach. .\" .Bh "Incorrect formats for printf and scanf" .\" .Pn Incorrect-formats-for-printf-and-scanf .\" .XX "C, warning, incorrect formats" .\" The function \s10\f(CWscanf\fR\s0 is usually defined as .\" .Ps .\" int scanf (const char *format, ...); .\" .Pe .\" The ellipses (\s8\f(CW...\fR\s0) state that a variable number of parameters may .\" follow: in fact, it is the format string that determines how many parameters to .\" use. Consider the following call to \s10\f(CWscanf\fR\s0: .\" .Ps .\" scanf ("%d %d %d %d", &i); .\" .Pe .\" The call syntax is correct, but \s10\f(CWscanf\fR\s0 will probably overwrite its .\" return information and generate a segmentation fault when it tries to return. .\" \fIgcc\fR can recognize this situation, if the \s10\f(CW-Wformat\fR\s0 option is .\" specified, by comparing the format string to the parameters. This requires the .\" format string to be a string literal. For example, it won't work with .\" .XX "C, gcc, -Wformat option" .\" .Ps .\" char *format = "%d %d %d %d"; .\" scanf (format, &i); .\" .Pe a317 12 .\" .Bh "Writeable strings" .\" .Pn Writeable-strings .\" .XX "C, warning, writeable strings" .\" .XX "C, gcc, -Wwrite-strings option" .\" There's nothing to stop you from writing code that writes into string constants. .\" This may or may not not work at run time, depending on the way the compiler .\" generates the code--see \*[chcompiler], page \*[writeable-strings] for more .\" details. If you start \fIgcc\fR with the \s10\f(CW-Wwrite-strings\fR\s0 option, .\" it gives string constants the type \s10\f(CWconst char []\fR\s0. This causes a .\" warning if you assign string constants to \s10\f(CWchar *\fR\s0 pointers. This .\" works properly only if you are religious about using \s10\f(CWconst\fR\s0 in .\" declarations and prototypes--otherwise you get lots of irrelevant messages. a350 13 .\" .Bh "Incorrectly initialized aggregates" .\" .Pn Incorrectly-initialized-aggregates .\" .XX "C, warning, incorrectly initialized aggregates" .\" Consider the following code segment .\" .Ps .\" struct foo {int bar, baz; }; .\" struct frotzel {struct foo fritz; int franz; int erwin; }; .\" struct frotzel motzel = {1, 2, 3}; .\" .Pe .\" The first element of \s10\f(CWfrotzel\fR\s0 is of type \s10\f(CWstruct .\" foo\fR\s0, but the initializer assigns the value \s10\f(CW\&1\fR\s0 to it. If .\" the \s10\f(CW-W\fR\s0 option is specified, \fIgcc\fR options this as a warning. I .\" consider this to be an error. a400 7 .\" .Bh "Macro arguments in strings" .\" .Pn Macro-arguments-in-strings .\" .XX "C, warning, macro arguments in strings" .\" .XX "C, gcc, -traditional option" .\" Some older versions of C replaced a macro argument in a string by the actual .\" parameter. ANSI C does not do this, and the \fIgcc\fR preprocessor warns about .\" it unless the \s10\f(CW-traditional\fR\s0 option has been specified. a422 54 .\" .Bh "Aggregate returns" .\" .Pn Aggregate-returns .\" .XX "C, warning, aggregate returns" .\" In C, you can write code like .\" .Ps .\" struct foo .\" { .\" float y; .\" int x; .\" char text [20]; .\" }; .\" .\" struct foo fritz; .\" struct foo *franz; .\" .\" struct foo bar () .\" { .\" static struct foo foobar; /* return this struct */ .\" \fI\&...\f(CW .\" return foobar; .\" } .\" .\" struct foo *baz () .\" { .\" static struct foo foobaz; /* return a pointer to this struct */ .\" \fI\&...\f(CW .\" return &foobaz; .\" } .\" .\" main () .\" { .\" \fI\&...\f(CW .\" fritz = bar (); .\" franz = baz (); .\" .Pe .\" The size of \s10\f(CWfoo\fR\s0 is about 32 bytes, depending on your .\" \s10\f(CWint\fR\s0 and \s10\f(CWfloat\fR\s0 representation. This may seem a .\" minor detail, but consider the two statements in \s10\f(CWmain\fR\s0: .\" .Ls B .\" .Li .\" In \s10\f(CWfritz = bar ()\fR\s0, \s10\f(CWbar\fR\s0 computes a result and then .\" returns the complete result to the calling function. To do this, the compiler .\" typically copies the struct to a private global area before leaving the .\" function. Back in \s10\f(CWmain\fR\s0, it copies this area into .\" \s10\f(CWfritz\fR\s0. This is not a very efficient way to do things, even with .\" 32 bytes. .\" .Li .\" \s10\f(CWfranz = baz ()\fR\s0 looks just the same, but here \s10\f(CWbaz\fR\s0 .\" just returns a pointer to \s10\f(CWfoobaz\fR\s0, which is stored in .\" \s10\f(CWfranz\fR\s0, and is much faster. .\" .Le .\" .XX "C, gcc, -Waggregate-return option" .\" It's easy to confuse these two ways of returning struct information. \fIgcc\fR .\" warns you if you specify the \s10\f(CW-Waggregate-return\fR\s0 option. a680 61 .\" , otherwise you might end up with something like this example .\" from an early version of Informix ESQL: .\" .Ps .\" #line 3326 "d3form.ec" .\" .\" date = key->valid_from; .\" .\" malloccheck (new = (struct mdef *) malloc (sizeof (struct mdef)), .\" (&d3xstr[7043]) ); .\" .\" { .\" static char *_sqlcmdtxt[] = { .\" (&d3xstr[7081]), .\" (&d3xstr[7157]), .\" 0}; .\" static _SQCURSOR _SQ0 = {0}; .\" .\" static struct sqlvar_struct _sqibind[] = { .\" {103, sizeof(long)}, .\" {103, sizeof(long)}, .\" }; .\" .\" static struct sqlvar_struct _sqobind[] = { .\" {103, sizeof(long)}, .\" {100, 21}, .\" {103, sizeof(long)}, .\" {103, sizeof(long)}, .\" }; .\" _sqibind[0].sqldata =(char *)&date; .\" _sqibind[1].sqldata =(char *)&date; .\" _sqobind[0].sqldata =(char *)&mdef.field_number; \fI\&line 3352\f(CW .\" _sqobind[1].sqldata =mdef.default_value; .\" _sqobind[2].sqldata =(char *)&mdef.valid_from; .\" _sqobind[3].sqldata =(char *)&mdef.valid_to; .\" _iqslct(&_SQ0, _sqlcmdtxt, 2, _sqibind, 4, _sqobind); .\" ;} .\" .\" #line 3343 "d3form.ec" .\" new->field_number = mfld.field_number; /* take this entry anyway */ .\" if (! sqlca.sqlcode) /* found--isn't this fun? */ .\" { .\" new->field_number = mdef.field_number; .\" strcpy (new->default_value, mdef.default_value); .\" new->valid_from = mdef.valid_from; .\" new->valid_to = mdef.valid_to; .\" } .\" else .\" new->default_value [0] = '0円'; /* no default */ \fI\&line 3352\f(CW .\" CHKSQLERR ((&d3xstr[7225])); .\" *data = new; /* return it */ .\" } .\" .Pe .\" .XX "C, #line directive" .\" The problem with this code is that there are 33 lines of code between the two .\" \fI#line\fR directives, which are supposed to be 17 lines apart. The original .\" SQL \fIselect\fR statement has been expanded to many more output lines. This .\" doesn't worry the compiler, but it means that we have two lines with the line .\" number 3352. If you want to set a breakpoint on the real line 3352 (the second .\" one), there's a good chance that you will set it on the first occurrence .\" instead. If you single step through such code, the debugger will try to map the .\" line numbers to the original source file and show you complete garbage. a697 2 .\" AMAZING! You got the \n to print right the first time! This is a .\" seriously good sign. @ 1.5 log @Final draft, first cut. @ text @d2 1 a2 1 .\" $Id: compiling.ms,v 1.4 1995年06月09日 04:31:01 grog Exp grog $ d4 3 d654 1 a654 1 In almost every such case, you will find one of two problems: d664 2 a665 2 developed. This header file does something different on your system, so the symbol you need is never defined. d748 3 a750 3 look at this in more detail in \*[chcompiler], on page \*[cc]. At the moment, we just need to recall that programs are compiled in two stages: first, the preprocessor expands all preprocessor definitions and macros, and then the d1024 2 a1025 2 \*[chcompiler], page \*[cc], for more details. Sometimes running the passes separately can be useful for debugging a compilation: d1070 1 a1070 1 \*[chcompiler], page \*[cc] for more details. @ 1.4 log @Remove date from page headers Minor mods @ text @d2 1 a2 1 .\" $Id: compiling.ms,v 1.3 1995年05月17日 06:00:34 grog Exp grog $ d4 4 d80 1 a80 1 Problems related to program flow. These are detected by the flow analysis phase d232 1 d310 6 a315 6 older model HP LaserJet printers. This code does not work: by default, the character \s10\f(CW*s\fR\s0 is a signed value, and so the characters \s10\f(CW0x80\fR\s0 to \s10\f(CW0xff\fR\s0 are expanded to a negative array offset, and the program attempts (maybe successfully) to access a byte outside the table \s10\f(CWiso_translate\fR\s0. \fIgcc\fR warns about this if you set the option \f(CW-Wchar-subscripts\fR\s0. d357 1 a357 1 .\" specified, by comparing the format string to the parameters. This requires d663 10 d798 3 a800 3 empty lines are where comments and preprocessor directives used to be. I was looking for line 156 of \fIprotoize.c\fR, so I searched for lines with \s10\f(CWprotoize.c\fR\s0 on them. I found a number of them: d1021 1 a1021 1 \*[chcompiler], page \*[cc], for more details. Sometimes running the phases d1043 1 a1043 1 compilation after the compiler phase and collect the generated assembler output. d1063 1 a1063 1 \f(CW-v\fR option for the compiler, which "announces" each phase of compilation d1065 1 a1065 1 phase. This makes it relatively easy to figure out which pass is printing the @ 1.3 log @Major mods after Andy's final draft review @ text @d2 1 a2 1 .\" $Id: compiling.ms,v 1.2 1995年02月14日 11:28:58 grog Exp grog $ d4 3 d19 1 a19 1 .St "Running the compiler ($Date: 1995年02月14日 11:28:58 $)" d27 3 a29 1 relates to other compilers as well, particularly of course to C++. d91 1 a91 1 .Ref t \& n d143 1 a143 1 .\" 4\fR\s0. The \s10\f(CW-W\fR\s0 flag causes a warning to be issued for this kind d149 1 a149 1 .\" use. If you specify the \s10\f(CW-Wimplicit\fR\s0 flag to \fIgcc\fR, it issues a d151 1 a151 1 .\" .XX "C, gcc, -Wimplicit flag" d157 1 a157 1 .\" specify the \s10\f(CW-Wstrict-prototypes\fR\s0 flag to \fIgcc\fR, it warns you if d160 1 a160 1 .\" .XX "C, gcc, -Wstrict-prototypes flag" d167 2 a168 2 .\" the \s10\f(CW-Wmissing-prototypes\fR\s0 flag. .\" .XX "C, gcc, -Wmissing-prototypes flag" d189 1 a189 1 \s10\f(CW-Wreturn-type\fR\s0 flag to \fIgcc\fR. This causes the following d191 1 a191 1 .XX "C, gcc, -Wreturn-type flag" d231 1 a231 1 \f(CW-Wuninitialized\fR\s0 compiler flag, it warns you when this situation d234 1 a234 1 .XX "C, gcc, -Wuninitialized flag" d260 1 a260 1 unsigned. The flag \s10\f(CW-W\fR\s0 causes the compiler to issue warnings for d282 1 a282 1 .\" The \s10\f(CW-W\fR\s0 flag causes a warning to be issued when this kind of d310 2 a311 2 the flag \f(CW-Wchar-subscripts\fR\s0. .XX "C, gcc, -Wchar-subscripts flag" d318 2 a319 2 .\" other modules. Specify the \s10\f(CW-Wunused\fR\s0 flag to get these warnings. .\" .XX "C, gcc, -Wunused flag" d351 1 a351 1 .\" \fIgcc\fR can recognize this situation, if the \s10\f(CW-Wformat\fR\s0 flag is d354 1 a354 1 .\" .XX "C, gcc, -Wformat flag" d377 1 a377 1 \s10\f(CW-Wcast-qual\fR\s0 flag to \fIgcc\fR, it complains if you use a cast to d379 1 a379 1 .XX "C, gcc, -Wcast-qual flag" d396 1 a396 1 is allowed to do. If you specify the \s10\f(CW-Wcast-align\fR\s0 flag to d398 1 a398 1 .XX "C, gcc, -Wcast-align flag" d403 2 a404 2 .XX "C, gcc, -Wenum-clash flag" One of the advantage of \fIenums\fR is that they make type checking d406 2 a407 2 you specify the \s10\f(CW-Wenum-clash\fR\s0 flag to \fIgcc\fR, \fIand\fR you're compiling C++, it warns about sloppy use of \fIenum\fRs. d413 1 a413 1 .XX "C, gcc, -Wswitch flag" d422 1 a422 1 of the index variable. Specify the \s10\f(CW-Wswitch\fR\s0 flag for these d436 1 a436 1 .XX "C, gcc, -traditional flag" d441 1 a441 1 \s10\f(CW-traditional\fR\s0 flag. d445 1 a445 1 .\" .XX "C, gcc, -Wwrite-strings flag" d449 1 a449 1 .\" details. If you start \fIgcc\fR with the \s10\f(CW-Wwrite-strings\fR\s0 flag, d461 2 a462 2 page \*[longjmp-volatile] for more details. \fIgcc\fR flags this situation as a warning if you specify the \s10\f(CW-W\fR\s0 flag. This is a complicated d486 1 a486 1 encounters this and the flag \s10\f(CW-W\fR\s0 has been set. d498 1 a498 1 .\" the \s10\f(CW-W\fR\s0 flag is specified, \fIgcc\fR flags this as a warning. I d503 1 a503 1 .XX "C, gcc, -Wtrigraphs flag" d506 1 a506 1 them, and so \fIgcc\fR supplies the flag \s10\f(CW-Wtrigraphs\fR\s0, which prints d508 1 a508 1 the flag \s10\f(CW-trigraphs\fR\s0 is used to enable them, it is not clear that d528 2 a529 2 \s10\f(CW-Wcomment\fR\s0 flag. .XX "C, gcc, -Wcomment flag" d545 1 a545 1 .XX "C, gcc, -Wparentheses flag" d548 1 a548 1 flag. By its nature, this flag is subjective, and you may find that it d553 1 a553 1 .\" .XX "C, gcc, -traditional flag" d556 1 a556 1 .\" it unless the \s10\f(CW-traditional\fR\s0 flag has been specified. d570 2 a571 2 .XX "C, gcc, -traditional flag" .XX "C, gcc, -Wnested-externs flag" d576 1 a576 1 function definition unless you supply the \s10\f(CW-traditional\fR\s0 flag. If d578 1 a578 1 supply the \s10\f(CW-Wnested-externs\fR\s0 flag as well. d630 1 a630 1 .\" .XX "C, gcc, -Waggregate-return flag" d632 1 a632 1 .\" warns you if you specify the \s10\f(CW-Waggregate-return\fR\s0 flag. d742 1 a742 1 compiler, usually by specifying the \s10\f(CW-E\fR\s0 flag--see your compiler d811 1 a811 1 .XX "C, gcc, -dD flag" d814 1 a814 1 \fIgcc\fR you can use the \s10\f(CW-dD\fR\s0 flag to keep the preprocessor d816 1 a816 1 directives. I used this flag as well, and found in \fIjunk.c\fR: d971 2 a972 1 symbol. d1006 2 a1007 2 page \*[cc] for more details. Sometimes running the phases separately can be useful for debugging a compilation: d1038 1 a1038 1 .XX "C, gcc, -v flag" d1048 5 a1052 5 \f(CW-v\fR flag for the compiler, which "announces" each phase of compilation as it starts, together with the version numbers and parameters passed to the phase. This makes it relatively easy to figure out which pass is printing the error messages. Otherwise you can run the passes individually--see \*[chcompiler], page \*[cc] for more details. @ 1.2 log @Minor mods @ text @d2 1 a2 1 .\" $Id: compiling.ms,v 1.1 1995年01月24日 17:18:09 grog Exp grog $ d4 3 d16 8 a23 4 .St "Running the compiler ($Date: 1995年01月24日 17:18:09 $)" In the previous chapter, we looked at building the package from the viewpoint of \fImake\fR. The other central program in the build process is the compiler. We'll restrict our attention to the C compiler, though much of what we discuss d29 4 a32 5 The compiler may issue \fIwarnings\fR, which are informational messages intended to draw attention to possible program errors. Their reliability and their value varies significantly: some are a sure-fire indication that something is wrong, while others may indicate possible problems and should be taken with a pinch of salt. d34 1 a34 1 The compiler may issue \fIerror\fR messages, indicating its convicition that it d36 1 a36 1 will suppress the output module, though you can't always rely on this. a40 3 In this chapter, we'll look at the things that typical compilers have in store for you when you're building a package. In \*[chcompile] we'll look at how the compiler works and how the various flavours of C differ from each other. d82 6 a87 5 detected and how reliable they are. We'll use the GNU C compiler warning messages a basis, since the GNU C compiler has a particularly large choice of warning messages, and since it is also widely used. Other compilers will warn about the same kind of problems, but the messages may be different. Here's an overview of the warnings we'll see: d94 12 a105 9 Expressions with no effect#\*[Expressions-with-no-effect] Implicit declarations#\*[Implicit-declarations] Incomplete function prototypes#\*[Incomplete-function-prototypes] Missing function prototypes in headers#\*[Missing-function-prototypes-in-headers] Implicit return type#\*[Implicit-return-type] Inconsistent function returns#\*[Inconsistent-function-returns] Uninitialized variables#\*[Uninitialized-variables] Signed comparisons of unsigned values#\*[Signed-comparisons-of-unsigned-values] Dubious arithmetic comparisons#\*[Dubious-arithmetic-comparisons] a106 2 Unused variables#\*[Unused-variables] Incorrect formats for printf and scanf#\*[Incorrect-formats-for-printf-and-scanf] d108 1 a108 1 Increasing alignment requirements#\*[Increasing-alignment-requirements] d110 1 d112 2 a113 3 long indices for switch#\*[long-indices-for-switch] Writeable strings#\*[Writeable-strings] Changing non-volatile automatic variables#\*[Changing-non-volatile-automatic-variables] d115 4 a118 1 Incorrectly initialized aggregates#\*[Incorrectly-initialized-aggregates] d120 1 a120 5 Nested comments#\*[Nested-comments] Missing parentheses#\*[Missing-parentheses] Macro arguments in strings#\*[Macro-arguments-in-strings] Functions with embedded extern definitions#\*[Functions-with-embedded-extern-definitions] Aggregate returns#\*[Aggregate-returns] d124 40 a163 40 .Bh "Expressions with no effect" .Pn Expressions-with-no-effect .XX "C, warning, expressions with no effect" The possibility of confusion between the operators \s10\f(CW=\fR\s0 and \s10\f(CW==\fR\s0 can also lead to mistakes like: .Ps if (x> 3) a == 4; .Pe This is syntactically perfectly valid C code, but it doesn't do much: under certain circumstances, the value of \s10\f(CWa\fR\s0 is compared with 4. And nothing else. .LP This is almost certainly a typo: programmer had intended to write \s10\f(CWa = 4\fR\s0. The \s10\f(CW-W\fR\s0 flag causes a warning to be issued for this kind of construct. .Bh "Implicit declarations" .Pn Implicit-declarations .XX "C, warning, implicit declarations" In ANSI C, it is good practice to declare all functions and parameters before use. If you specify the \s10\f(CW-Wimplicit\fR\s0 flag to \fIgcc\fR, it issues a warning if a function or parameter name is used before being declared. .XX "C, gcc, -Wimplicit flag" .Bh "Incomplete function prototypes" .Pn Incomplete-function-prototypes .XX "C, warning, incomplete function prototypes" Some flavours of C allow "incomplete" function declarations, where the return type or the types of some parameters default to \s10\f(CWint\fR\s0. If you specify the \s10\f(CW-Wstrict-prototypes\fR\s0 flag to \fIgcc\fR, it warns you if you declare or define a function without supplying the full information about parameters and return type. .XX "C, gcc, -Wstrict-prototypes flag" .Bh "Missing function prototypes in headers" .Pn Missing-function-prototypes-in-headers .XX "C, warning, missing function prototypes" You can be even more pedantic about function prototypes and require that there should always be a function declaration in a header file before you encounter the function definition. You can get \fIgcc\fR to do this, too, by specifying the \s10\f(CW-Wmissing-prototypes\fR\s0 flag. .XX "C, gcc, -Wmissing-prototypes flag" d208 1 a208 1 invocation on a particular architecture (probably the value of d226 3 a228 3 \f(CW-Wuninitialized\fR\s0 compiler flag, it warns you when this situation occurs. Current versions of \fIgcc\fR place some limitations on this test--other compilers, including newer versions of \fIgcc\fR, may not: d230 12 a241 12 .Ls B .Li It works only when the optimizer is in use, since it relies on data flow information computed by the optimizer. .Li It occurs only for variables that could be stored in registers. This excludes \s10\fIvolatile\fR\s0 variables, variables whose address is used explicitly, and variables with sizes other than 1, 2, 4 or 8 bytes. .XX "C, volatile type qualifier" .Li It also excludes structures, unions and arrays. .Le d256 23 a278 23 this situation. .Bh "Dubious arithmetic comparisons" .Pn Dubious-arithmetic-comparisons .XX "C, warning, dubious comparisons" The statment .Ps if (a <= b <= c) .Pe is perfectly syntactically valid C. First, it compares the values of \s10\f(CWa\fR\s0 and \s10\f(CWb\fR\s0. The result of this comparison (0, if \s10\f(CWa\fR\s0 is greater than \s10\f(CWb\fR\s0, 1 otherwise) is compared with \s10\f(CWc\fR\s0. This may be what is intended, of course, but then it would be better to write it as .Ps if ((a <= b) <= c) .Pe which means the same thing. The original notation looks so much like mathematical notation that the author probably intended to write: .Ps if ((a <= b) && (b <= c)) .Pe The \s10\f(CW-W\fR\s0 flag causes a warning to be issued when this kind of construct is encountered. d307 47 a353 47 .Bh "Unused variables" .Pn Unused-variables .XX "C, warning, unused variables" As we discussed at the beginning of the section, the compiler can detect and report variables that are defined but not used. Non-static global variables are excluded from this test, since they are known externally and could be used by other modules. Specify the \s10\f(CW-Wunused\fR\s0 flag to get these warnings. .XX "C, gcc, -Wunused flag" .LP Occasionally, this can be a nuisance. For example, if you are using RCS, you might have the following code: .Ps static char rcs_id [] = "$\&Id: foo.c,v 1.6 1994/08/07 11:49:03 grog Exp grog $"; .Pe The compiler complains about every one of these, since nothing in the program refers to it. The \fIgcc\fR documentation suggests that you can prevent this warning with the following macro: .Ps #define USE(var) static void * use_##var = (&use_##var, (void *) &var) USE (string); .Pe This creates a pointer to the string, which takes up space, but gets rid of the warning message. It's your decision whether this is a cleaner approach. .Bh "Incorrect formats for printf and scanf" .Pn Incorrect-formats-for-printf-and-scanf .XX "C, warning, incorrect formats" The function \s10\f(CWscanf\fR\s0 is usually defined as .Ps int scanf (const char *format, ...); .Pe The ellipses (\s8\f(CW...\fR\s0) state that a variable number of parameters may follow: in fact, it is the format string that determines how many parameters to use. Consider the following call to \s10\f(CWscanf\fR\s0: .Ps scanf ("%d %d %d %d", &i); .Pe The call syntax is correct, but \s10\f(CWscanf\fR\s0 will probably overwrite its return information and generate a segmentation fault when it tries to return. \fIgcc\fR can recognize this situation, if the \s10\f(CW-Wformat\fR\s0 flag is specified, by comparing the format string to the parameters. This requires format string to be a string literal. For example, it won't work with .XX "C, gcc, -Wformat flag" .Ps char *format = "%d %d %d %d"; scanf (format, &i); .Pe d372 2 a373 2 \s10\f(CW-Wcast-qual\fR\s0 flag to \fIgcc\fR, it complains anyway if you use a cast to remove a type qualifier such as \s10\fIconst\fR\s0. d380 3 a382 3 boundaries, and that the results can be spectacular if they are not--see \*[chhard], page \*[wordalign], for more details. We can easily outsmart the C compiler with code like: d402 1 a402 1 compiling C++, it warns about this. d416 1 a416 1 \s10\f(CWcase\fR\s0 clauses exist for values which are not defined for the type d437 12 a448 12 .Bh "Writeable strings" .Pn Writeable-strings .XX "C, warning, writeable strings" .XX "C, gcc, -Wwrite-strings flag" There's nothing to stop you from writing code that writes into string constants. This may or may not not work at run time, depending on the way the compiler generates the code--see \*[chcompiler], page \*[writeable-strings] for more details. If you start \fIgcc\fR with the \s10\f(CW-Wwrite-strings\fR\s0 flag, it gives string constants the type \s10\f(CWconst char []\fR\s0. This causes a warning if you assign string constants to \s10\f(CWchar *\fR\s0 pointers. This works properly only if you are religious about using \s10\f(CWconst\fR\s0 in declarations and prototypes--otherwise you get lots of irrelevant messages. d455 4 a458 3 variable if the function has called \s10\f(CWsetjmp\fR\s0--see \*[chcompiler], page \*[volatile] for more details. \fIgcc\fR flags this situation as a warning if you specify the \s10\f(CW-W\fR\s0 flag. This is a complicated problem: d462 1 a462 1 \s10\fIvolatile\fR\s0 only has meaning in these circumstances. In addition, the d482 13 a494 13 .Bh "Incorrectly initialized aggregates" .Pn Incorrectly-initialized-aggregates .XX "C, warning, incorrectly initialized aggregates" Consider the following code segment .Ps struct foo {int bar, baz; }; struct frotzel {struct foo fritz; int franz; int erwin; }; struct frotzel motzel = {1, 2, 3}; .Pe The first element of \s10\f(CWfrotzel\fR\s0 is of type \s10\f(CWstruct foo\fR\s0, but the initializer assigns the value \s10\f(CW\&1\fR\s0 to it. If the \s10\f(CW-W\fR\s0 flag is specified, \fIgcc\fR flags this as a warning. I consider this to be an error. d535 2 a536 2 evaluate the expression? You can find the real answer on page 53 of [K&R 88], but you don't want to do that all the time. We can re-write the code as d545 7 a551 7 .Bh "Macro arguments in strings" .Pn Macro-arguments-in-strings .XX "C, warning, macro arguments in strings" .XX "C, gcc, -traditional flag" Some older versions of C replaced a macro argument in a string by the actual parameter. ANSI C does not do this, and the \fIgcc\fR preprocessor warns about it unless the \s10\f(CW-traditional\fR\s0 flag has been specified. d574 54 a627 54 .Bh "Aggregate returns" .Pn Aggregate-returns .XX "C, warning, aggregate returns" In C, you can write code like .Ps struct foo { float y; int x; char text [20]; }; struct foo fritz; struct foo *franz; struct foo bar () { static struct foo foobar; /* return this struct */ \fI\&...\f(CW return foobar; } struct foo *baz () { static struct foo foobaz; /* return a pointer to this struct */ \fI\&...\f(CW return &foobaz; } main () { \fI\&...\f(CW fritz = bar (); franz = baz (); .Pe The size of \s10\f(CWfoo\fR\s0 is about 32 bytes, depending on your \s10\f(CWint\fR\s0 and \s10\f(CWfloat\fR\s0 representation. This may seem a minor detail, but consider the two statements in \s10\f(CWmain\fR\s0: .Ls B .Li In \s10\f(CWfritz = bar ()\fR\s0, \s10\f(CWbar\fR\s0 computes a result and then returns the complete result to the calling function. To do this, the compiler typically copies the struct to a private global area before leaving the function. Back in \s10\f(CWmain\fR\s0, it copies this area into \s10\f(CWfritz\fR\s0. This is not a very efficient way to do things, even with 32 bytes. .Li \s10\f(CWfranz = baz ()\fR\s0 looks just the same, but here \s10\f(CWbaz\fR\s0 just returns a pointer to \s10\f(CWfoobaz\fR\s0, which is stored in \s10\f(CWfranz\fR\s0, and is much faster. .Le .XX "C, gcc, -Waggregate-return flag" It's easy to confuse these two ways of returning struct information. \fIgcc\fR warns you if you specify the \s10\f(CW-Waggregate-return\fR\s0 flag. d632 2 a633 2 compiler--they are still the most common reason for a build to fail. In this section, we'll look at some of the more common ones. d636 4 a639 5 One of the most frequent compiler error messages you see during porting is that a symbol is not defined. At first sight, it seems strange that the compiler should find undefined symbols in a program which has already been installed on another platform: if there are such primitive errors in it, how could it have worked? d645 1 a645 1 The definition you need may have been \fI#ifdef\fR'ed out. For example, in a d651 1 a651 1 developed; this header file does something different on your system, so the d667 2 a668 2 Something similar happens on newer System V systems with POSIX.1 compatibility: a program that seems formally correct may fail to compile with an undefined d678 9 a686 4 The solution seems straightforward enough: \f(CW#undef _POSIX_SOURCE\fR. If you do this, you may find that suddenly other macros are undefined, for example \f(CWO_NOCTTY\fR. System V.4 only defines this variable if \f(CW_POSIX_SOURCE\fR is set. d688 4 a691 4 There's no obvious general solution to this problem. It is caused by messy programming style: the programmer has mixed symbols defined only by POSIX.1 with those which are not defined in POSIX.1. The program may run on your current system, but may stop doing so at the next release. d738 2 a739 2 documentation and \*[appcompflags], for more details. In this case, I was running the compiler in an \fIxterm\fR\**, d741 3 a743 3 \fIxterm\fR is a terminal emulator program which runs under X11. If you don't use it, you should--for example, it makes this particular technique much easier. technique I describe. d762 1 a762 1 \fIjunk.c\fR consists of mainly empty lines. It starts with: d798 3 a800 3 extern int ((fputs(( ), stdout) || (( stdout )->__bufp < ( stdout )->__put_limit ? (int) (unsigned char) (*( stdout )->__bufp++ = (unsigned char) ( '\n' )) :__flshfp (( stdout ), (unsigned char) ( '\n' ))) == (-1) ) ? (-1) : 0) ; d815 1 a815 1 extern int fputs (__const char *__s, FILE *__stream) ; d817 1 a817 1 extern int puts (__const char *__s) ; d819 1 a819 1 #define puts(s) ((fputs((s), stdout) || __putc('\n', stdout) == EOF) ? EOF : 0) d826 1 a826 1 extern int puts __P ((__const char *__s)); d828 2 a829 2 #ifdef __OPTIMIZE__ #define puts(s) ((fputs((s), stdout) || __putc('\n', stdout) == EOF) ? EOF : 0) d837 1 a837 1 \s10\f(CWputs\fR\s0 again. There are many programs which try to out-guess d864 3 a866 3 file that the compiler gets. Examples are \fIyacc\fR and \fIbison\fR, which take a grammar file and make a (more or less illegible) \fI\&.c\fR file out of it; other examples are database preprocessors like Informix ESQL, which takes C d873 64 a936 62 Not all of them do it correctly: the preprocessor should not insert extra lines into the source, otherwise you might end up with something like this example from an early version of Informix ESQL: .Ps #line 3326 "d3form.ec" date = key->valid_from; malloccheck (new = (struct mdef *) malloc (sizeof (struct mdef)), (&d3xstr[7043]) ); { static char *_sqlcmdtxt[] = { (&d3xstr[7081]), (&d3xstr[7157]), 0}; static _SQCURSOR _SQ0 = {0}; static struct sqlvar_struct _sqibind[] = { {103, sizeof(long)}, {103, sizeof(long)}, }; static struct sqlvar_struct _sqobind[] = { {103, sizeof(long)}, {100, 21}, {103, sizeof(long)}, {103, sizeof(long)}, }; _sqibind[0].sqldata =(char *)&date; _sqibind[1].sqldata =(char *)&date; _sqobind[0].sqldata =(char *)&mdef.field_number; \fI\&line 3352\f(CW _sqobind[1].sqldata =mdef.default_value; _sqobind[2].sqldata =(char *)&mdef.valid_from; _sqobind[3].sqldata =(char *)&mdef.valid_to; _iqslct(&_SQ0, _sqlcmdtxt, 2, _sqibind, 4, _sqobind); ;} #line 3343 "d3form.ec" new->field_number = mfld.field_number; /* take this entry anyway */ if (! sqlca.sqlcode) /* found--isn't this fun? */ { new->field_number = mdef.field_number; strcpy (new->default_value, mdef.default_value); new->valid_from = mdef.valid_from; new->valid_to = mdef.valid_to; } else new->default_value [0] = '0円'; /* no default */ \fI\&line 3352\f(CW CHKSQLERR ((&d3xstr[7225])); *data = new; /* return it */ } .Pe .XX "C, #line directive" The problem with this code is that there are 33 lines of code between the two \fI#line\fR directives, which are supposed to be 17 lines apart. The original SQL \fIselect\fR statement has been expanded to many more output lines. This doesn't worry the compiler, but it means that we have two lines with the line number 3352. If you want to set a breakpoint on the real line 3352 (the second one), there's a good chance that you will set it on the first occurrence instead. If you single step through such code, the debugger will try to map the line numbers to the original source file and show you complete garbage. d940 2 a941 2 undefined symbols, but they hit in a different way. A favourite one results from omitting \fI/usr/include/sys/types.h\fR. For example, consider d973 4 a976 3 MB of memory space, and on occasion it can use up to 32 MB. If your system has less than this available, increase the limit accordingly. Don't forget to ensure that you have enough swap space! d999 3 a1001 5 Typical compilers runn four distinct passes to compile and link a program--see page \*[cc] for more details. Running the linker separately is very common; running the assembler is the way to assemble \fI\&.s\fR files; but the first three phases usually run without interruption. Sometimes running the other phases separately can be useful as well: d1009 1 a1009 1 output for \fIfoo.c\fR would be called \fIfoo.i\fR--see \*[chcompile], page d1011 3 a1013 2 does no harm to pass preprocessed output through a preprocessor, since there should no longer be anything for the second preprocessor to do. d1040 1 a1040 1 the message There are various ways to confirm which pass of the compiler @ 1.1 log @Initial revision @ text @d2 5 a6 2 .\" $Id: building.ms,v 1.1 1995年01月23日 09:27:18 grog Exp grog $ .\" $Log: building.ms,v $ d13 2 a14 2 .St "Running the compiler ($Date: 1995年01月23日 09:27:18 $)" In the last chapter, we looked at building the package from the viewpoint of d44 1 d47 1 a47 1 since it is available only on System V systems. This is a pity, because a48 1 .XX "lint, program" d686 1 a686 1 For example, porting \fIgcc\fR, you could run into this problem: d698 1 a698 3 If you look at this part of \fIprotoize.c\fR, you'll see lots of external definitions: d715 23 a737 6 In cases like this, it's good to remember that the compiler is \fInot\fR looking at this source file: the file has already passed through the preprocessor, and by the time it gets to the compiler it looks quite different. Let's look at the code that the compiler sees. We use the \s10\f(CW-E\fR\s0 flag to tell the compiler to stop after the preprocessor phase. In this case, we append to the command line: d749 5 a753 3 We call the output file \fIjunk.c\fR, not the more correct \fIjunk.i\fR, because \fIemacs\fR doesn't understand the suffix \fI.i\fR, and so it does not load the correct macros. \fIjunk.c\fR consists of mainly empty lines. It starts with: d769 3 a771 3 empty lines are where comments and preprocessor directives used to be. We're looking for line 156 of \fIprotoize.c\fR, so we should search for lines with \s10\f(CWprotoize.c\fR\s0 on them. We find a number of them: d783 3 a785 3 Clearly, our text is between lines 78 and 222. We position on the line \fIafter\fR the marker for line 78 and move down (156 - 78) or 78 lines. There we find: d798 5 a802 5 Well, at any rate it's now clear why the compiler was complaining. But where did this junk come from? It can be difficult to figure this out. With \fIgcc\fR you can use the \s10\f(CW-dD\fR\s0 flag to keep the preprocessor definitions--unfortunately, the other preprocessor directives are still removed. If we use this flag as well, we find in \fIjunk.c\fR: d812 3 a814 4 This looks strange: first we declare \s10\f(CWputs\fR\s0 as an external function, then we define it as a macro. This doesn't worry the preprocessor, but the results certainly worry the compiler. Looking at the original source of \fIstdio.h\fR, we see: d825 15 a839 3 \s10\f(CW#else\fR\s0 clause. But that's not the real problem: there are too many programs like \fIprotoize\fR which try to define external functions where they're not needed: this kind of definition would break them all. @

AltStyle によって変換されたページ (->オリジナル) /