=head1 COMMON PROBLEMS
-Perl source plays by ANSI C89 rules: no C99 (or C++) extensions. In
-some cases we have to take pre-ANSI requirements into consideration.
+Perl source plays by ANSI C89 rules: no C99 (or C++) extensions.
You don't care about some particular platform having broken Perl? I
hear there is still a strong demand for J2EE programmers.
-pedantic> flags which enforce stricter ANSI rules.
If using the C<gcc -Wall> note that not all the possible warnings (like
-C<-Wunitialized>) are given unless you also compile with C<-O>.
+C<-Wuninitialized>) are given unless you also compile with C<-O>.
Note that if using gcc, starting from Perl 5.9.5 the Perl core source
code files (the ones at the top level of the source code distribution,
Assuming one can dereference any type of pointer for any type of data
char *p = ...;
- long pony = *p; /* BAD */
+ long pony = *(long *)p; /* BAD */
Many platforms, quite rightly so, will give you a core dump instead of
a pony if the p happens not to be correctly aligned.
That is C99 or C++. Some C compilers allow that, but you shouldn't.
-The gcc option C<-Wdeclaration-after-statements> scans for such
+The gcc option C<-Wdeclaration-after-statement> scans for such
problems (by default on starting from Perl 5.9.4).
=item *
printf("i = %"IVdf"\n", (IV)something_very_small_and_signed);
+See L<perlguts/Formatted Printing of Size_t and SSize_t> for how to
+print those.
+
Also remember that the C<%p> format really does require a void pointer:
U8* p = ...;
To really poke around with Perl, you'll probably want to build Perl for
debugging, like this:
- ./Configure -d -D optimize=-g
+ ./Configure -d -DDEBUGGING
make
-C<-g> is a flag to the C compiler to have it produce debugging
-information which will allow us to step through a running program, and
-to see in which C function we are at (without the debugging information
-we might see only the numerical addresses of the functions, which is
-not very helpful).
-
-F<Configure> will also turn on the C<DEBUGGING> compilation symbol
-which enables all the internal debugging code in Perl. There are a
-whole bunch of things you can debug with this: L<perlrun> lists them
-all, and the best way to find out about them is to play about with
-them. The most useful options are probably
+C<-DDEBUGGING> turns on the C compiler's C<-g> flag to have it produce
+debugging information which will allow us to step through a running
+program, and to see in which C function we are at (without the debugging
+information we might see only the numerical addresses of the functions,
+which is not very helpful). It will also turn on the C<DEBUGGING>
+compilation symbol which enables all the internal debugging code in Perl.
+There are a whole bunch of things you can debug with this: L<perlrun>
+lists them all, and the best way to find out about them is to play about
+with them. The most useful options are probably
l Context (loop) stack processing
+ s Stack snapshots (with v, displays all stacks)
t Trace execution
o Method and overloading resolution
c String/numeric conversions
-Some of the functionality of the debugging code can be achieved using
-XS modules.
+For example
+
+ $ perl -Dst -e '$a + 1'
+ ....
+ (-e:1) gvsv(main::a)
+ => UNDEF
+ (-e:1) const(IV(1))
+ => UNDEF IV(1)
+ (-e:1) add
+ => NV(1)
+
+
+Some of the functionality of the debugging code can be achieved with a
+non-debugging perl by using XS modules:
-Dr => use re 'debug'
-Dx => use O 'Debug'
libraries, and then:
Breakpoint 1, Perl_pp_add () at pp_hot.c:309
- 309 dSP; dATARGET; tryAMAGICbin(add,opASSIGN);
+ 1396 dSP; dATARGET; bool useleft; SV *svl, *svr;
(gdb) step
311 dPOPTOPnnrl_ul;
(gdb)
We can also dump out this op: the current op is always stored in
C<PL_op>, and we can dump it with C<Perl_op_dump>. This'll give us
-similar output to L<B::Debug|B::Debug>.
+similar output to CPAN module B::Debug.
(gdb) print Perl_op_dump(PL_op)
{
execution and data flows. As a matter of fact, this is exactly how C
compilers know to give warnings about dubious code.
-=head2 lint, splint
+=head2 lint
The good old C code quality inspector, C<lint>, is available in several
platforms, but please be aware that there are several different
implementations of it by different vendors, which means that the flags
are not identical across different platforms.
-There is a lint variant called C<splint> (Secure Programming Lint)
-available from http://www.splint.org/ that should compile on any
-Unix-like platform.
-
-There are C<lint> and <splint> targets in Makefile, but you may have to
+There is a C<lint> target in Makefile, but you may have to
diddle with the flags (see above).
=head2 Coverity
-Coverity (http://www.coverity.com/) is a product similar to lint and as
+Coverity (L<http://www.coverity.com/>) is a product similar to lint and as
a testbed for their product they periodically check several open source
projects, and they give out accounts to open source developers to the
defect databases.
There is Coverity setup for the perl5 project:
L<https://scan.coverity.com/projects/perl5>
-=head HP-UX cadvise (Code Advisor)
+=head2 HP-UX cadvise (Code Advisor)
HP has a C/C++ static analyzer product for HP-UX caller Code Advisor.
(Link not given here because the URL is horribly long and seems horribly
changed, too. Therefore such code should probably be turned into a
subroutine or a macro.
-cpd (http://pmd.sourceforge.net/cpd.html) is part of the pmd project
-(http://pmd.sourceforge.net/). pmd was originally written for static
+cpd (L<http://pmd.sourceforge.net/cpd.html>) is part of the pmd project
+(L<http://pmd.sourceforge.net/>). pmd was originally written for static
analysis of Java code, but later the cpd part of it was extended to
parse also C and C++.
C<cflags> frontend selects C<-ansi -pedantic> for the platforms where
they are known to be safe.
-Starting from Perl 5.9.4 the following extra flags are added:
+The following extra flags are added:
=over 4
=item *
-C<-Wdeclaration-after-statement>
+C<-Wc++-compat>
+
+=item *
+
+C<-Wwrite-strings>
+
+=item *
+
+C<-Werror=declaration-after-statement>
+
+=item *
+
+C<-Werror=pointer-arith>
=back
=item *
-C<-Wpointer-arith>
-
-=item *
-
C<-Wshadow>
=item *
=back
See also
-L<http://code.google.com/p/address-sanitizer/wiki/AddressSanitizer>.
+L<https://github.com/google/sanitizers/wiki/AddressSanitizer>.
=head1 PROFILING
equivalent of setting this variable to the value 1.)
If, at the end of a run you get the message I<N scalars leaked>, you
-can recompile with C<-DDEBUG_LEAKING_SCALARS>, which will cause the
+can recompile with C<-DDEBUG_LEAKING_SCALARS>,
+(C<Configure -Accflags=-DDEBUG_LEAKING_SCALARS>), which will cause the
addresses of all those leaked SVs to be dumped along with details as to
where each SV was originally allocated. This information is also
displayed by Devel::Peek. Note that the extra details recorded with
=head2 PERL_MEM_LOG
-If compiled with C<-DPERL_MEM_LOG>, both memory and SV allocations go
-through logging functions, which is handy for breakpoint setting.
+If compiled with C<-DPERL_MEM_LOG> (C<-Accflags=-DPERL_MEM_LOG>), both
+memory and SV allocations go through logging functions, which is
+handy for breakpoint setting.
-Unless C<-DPERL_MEM_LOG_NOIMPL> is also compiled, the logging functions
-read $ENV{PERL_MEM_LOG} to determine whether to log the event, and if
-so how:
+Unless C<-DPERL_MEM_LOG_NOIMPL> (C<-Accflags=-DPERL_MEM_LOG_NOIMPL>) is
+also compiled, the logging functions read $ENV{PERL_MEM_LOG} to
+determine whether to log the event, and if so how:
$ENV{PERL_MEM_LOG} =~ /m/ Log all memory ops
$ENV{PERL_MEM_LOG} =~ /s/ Log all SV ops
=head2 When is a bool not a bool?
On pre-C99 compilers, C<bool> is defined as equivalent to C<char>.
-Consequently assignment of any larger type to a C<bool> is unsafe and may
-be truncated. The C<cBOOL> macro exists to cast it correctly.
+Consequently assignment of any larger type to a C<bool> is unsafe and may be
+truncated. The C<cBOOL> macro exists to cast it correctly; you may also find
+that using it is shorter and clearer than writing out the equivalent
+conditional expression longhand.
On those platforms and compilers where C<bool> really is a boolean (C++,
C99), it is easy to forget the cast. You can force C<bool> to be a C<char>
or your compiler's equivalent to make it easier to spot any unsafe truncations
that show up.
+The C<TRUE> and C<FALSE> macros are available for situations where using them
+would clarify intent. (But they always just mean the same as the integers 1 and
+0 regardless, so using them isn't compulsory.)
+
=head2 The .i Targets
You can expand the macros in a F<foo.c> file by saying