C/C++ development and debugging.

Some random svn notes.

April 28, 2016 C/C++ development and debugging. , , , , , , , , ,

Pull

svn update

If there are conflicts, then an (e) edit option is available.  SVN isn’t smart enough to notice that resolving the conflict can be complete at edit completion, so you have to mark each such resolved change (r) resolved explicitly after invoking edit.

For unfathomable reasons, SVN (e)dit conflicts are shown in ‘diff -u’ output instead of ‘diff3 -m’.  I’m hoping that oddity can be confligured away.

svn status -u : if you mark a merge conflict as deferred, then this will show what all the contributors were.  In particular, you can construct a ‘diff3 -m’ command for such a deferred conflict, by running:

$ svn status -u | grep -A3 ^C
C            30427   lz_ios/lz_ios_srv/src/ios_config.c
?                    lz_ios/lz_ios_srv/src/ios_config.c.mine
?                    lz_ios/lz_ios_srv/src/ios_config.c.r30417
?                    lz_ios/lz_ios_srv/src/ios_config.c.r30427

From this you can run:

$ diff3 -m \
                    lz_ios/lz_ios_srv/src/ios_config.c.mine \
                    lz_ios/lz_ios_srv/src/ios_config.c.r30417 \
                    lz_ios/lz_ios_srv/src/ios_config.c.r30427 \
> lz_ios/lz_ios_srv/src/ios_config.c

After resolving the conflict, and updating the file, you must run:

svn resolve –accept=working foo.c # (say)

Merge branch

For a branch off of the project ‘foo’ :

svn up
svn merge --accept postpone ^/foo/trunk
svn commit 

Then resolve conflicts as above with ‘svn update’

Push (local branch, or local changes to trunk)

$ svn commit

Query stuff

svn diff, and svn log.

Cleanup state from failed update

When running over flaky wireless, my svn update’s failed a few times.  You have to run ‘svn cleanup’ to handle such a failure (but it tells you to do so).

Build tree root and repo info

‘svn info’ gives you useful information about the build tree you are in (the svn checkout).

List files and other info for a commit

svn log -v -r 30414

Commit selectively.

List the files:

svn ci -F ../../tools/svn-commit.tmp `cat c`

 

Accidental correctness

October 6, 2015 C/C++ development and debugging. ,

Here’s a fun warning message I saw today:


foo.h:408:15: warning: & has lower precedence than !=; != will be evaluated first [-Wparentheses]
  if( nibbles & 0x01 != 0 )
              ^~~~~~~~~~~
foo.h:408:15: note: place parentheses around the '!=' expression to silence this warning
  if( nibbles & 0x01 != 0 )
              ^
                (        )
foo.h:408:15: note: place parentheses around the & expression to evaluate it first
  if( nibbles & 0x01 != 0 )
              ^
      (             )

The author of the code appears to fluked out with this statement, since (0x01 != 0) == 1, which is exactly the bit that they were attempting to test against. Ironically, the != 0 was probably added for clarity, but if they had wanted to test against any other bit, the code wouldn’t have done what they expected, and “clarifying the statement” would have bugified it.

extern vs const in C++ and C code.

October 5, 2015 C/C++ development and debugging. , , , , , ,

We now build DB2 on linux ppcle with the IBM xlC 13.1.2 compiler. This version of the compiler is a hybrid compared to any previous compilers, retaining the IBM xlC backend for power, but using the clang front end. Because of this we are exposed to a large number of warnings that we don’t see with many other compilers (well we probably do for our MacOSX port, but we do not really have active development on that platform at the moment), and I’ve been trying to take down those counts to manageable levels. Header files that produce warnings have been my first target since they introduce the most repeated noise.

One message that I was seeing hundreds of was

warning: 'extern' variable has an initializer [-Wextern-initializer]

This seemed to be coming from headers that did something like:

#if defined FOO_INITIALIZE_IT_IN_SOME_SOURCE_FILE
extern const TYPE foo[] = { ... } ;
#else
extern const TYPE foo[] ;
#endif


where FOO_INITIALIZE_IT_IN_SOME_SOURCE_FILE is defined at the top of a source file that explicitly includes this header. My attempt to handle the messages was to remove the ‘extern’ from the initialization case, but I was suprised to see link errors as a result of some of those changes. It turns out that there are some subtle differences between different variations of const and extern with an array declaration of this sort. Here’s a bit of sample code:

// t.h
extern const int x[] ;
extern int y[] ;
extern int z[] ;


// t.cc
#if defined WANT_LINK_ERROR
const int x[] = { 42 } ;
#else
extern const int x[] = { 42 } ;
#endif

extern int y[] = { 42 } ;
int z[] = { 42 } ;


When WANT_LINK_ERROR isn’t defined, this produces just one clang warning message

t.cc:8:12: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern int y[] = { 42 } ;
           ^

Note that the ‘extern const’ has no such warning, nor does the non-const symbol that’s been declared ‘extern’ in the header. However, removing the extern from the const case (via -DWANT_LINK_ERROR) results in no symbol ‘x’ available to other consumers. The extern is required for const symbols, but generates a warning for non-const symbols.

It appears that this is also C++ specific. A const symbol in C compiled code is available for external use, regardless of whether extern is used:



$ clang -c t.c
t.c:5:18: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern const int x[] = { 42 } ;
                 ^
t.c:8:12: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern int y[] = { 42 } ;
           ^
2 warnings generated.

$ nm t.o
0000000000000000 R x
0000000000000000 D y
0000000000000004 D z

$ clang -c -DWANT_LINK_ERROR t.c
t.c:8:12: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern int y[] = { 42 } ;
           ^
1 warning generated.
$  nm t.o
0000000000000000 R x
0000000000000000 D y
0000000000000004 D z


whereas that same symbol requires extern if it is const in C++:


$ clang++ -c t.cc
t.cc:8:12: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern int y[] = { 42 } ;
           ^
1 warning generated.
$ nm t.o
0000000000000000 R x
0000000000000000 D y
0000000000000004 D z



$ clang++ -c -DWANT_LINK_ERROR t.cc
t.cc:8:12: warning: 'extern' variable has an initializer [-Wextern-initializer]
extern int y[] = { 42 } ;
           ^
1 warning generated.
$ nm t.o
0000000000000000 D y
0000000000000004 D z


I hadn’t expected the const to interact this way with extern. I am guessing that C++ allows for the compiler to not generate symbols for global scope const variables, unless you ask for that by using extern, whereas with C you get the symbol like-it-or-not. This particular message from the clang front end is only for non-const extern initializations, making across the board fixing of messages for extern initialization of the sort above trickier. This makes it so that you can’t do an across the board replacement of extern in initializers for a given file without first ensuring that the symbol isn’t const. It looks like dealing with this will have to be done much more carefully than I first tried.

Debugging with optimization: -g8

May 8, 2015 C/C++ development and debugging. , , , , ,

It was suggested to me to try -g8 for debugging some optimized code (xlC compiler, linuxppcle platform).  Turns out that there is a whole set of -gN options with the xlC compiler that allow various levels of debug instrumentation.

For the optimization bug that I was debugging, -g8 made the problem go away, but with -g5 I was able to break at the nearest case: block and determine that the data in the variables was good coming into that case statement.  Since what appears to come out of that case statement is bad, this isolates the problem significantly.

Hacking header file timestamps

May 7, 2015 C/C++ development and debugging. , , ,

Suppose you change a header foo.h, but your build system has dependency checking that will force the world to be rebuilt. A handy way to avoid that is with judicious use of the touch command, such as:

touch -t197301010000 foo.h 

or (on Linux)

touch --reference another-file-that-is-early-enough-in-time foo.h

Both of these can be used to force the modification time for the file backwards.

This can be very useful way to save time.

It is also a great way to not build enough or break the build if misused!

I’d recommend this only for prototyping type work, to be followed up with a subsequent touch to restore the timestamps to normal, and then do a proper build.