[cs631apue] Differences in FTS between Linux and BSD

Jan Schaumann jschauma at stevens.edu
Wed Oct 2 22:33:46 EDT 2019


Elliot Wasem <ewasem at stevens.edu> wrote:
 
> What's happening is that when I call
> fts_children(my_FTS_ptr, 0) after calling
> fts_read(my_FTS_ptr), it's segfaulting. If I print
> strerror(errno) right before calling
> fts_children(...), it says that it failed to
> allocate memory. When I run $gdb ./ls ./ls.core, it
> just says there's an error at ?? (literally prints
> ??) at libc.so.12.

Your libc was not built with debugging symbols, so the
debugger can't tell you much about that particular
place in the library.  However, it should be able to
tell you where in _your_ program the execution
triggered the segfault.

For that, make sure to compile your program with
debugging symbols enabled ('-g'), then use 'bt' in the
debugger to inspect the frame stack and select the
frame in which you failed in your code.

For example, use the file gdb2.c from the code
examples from Monday's lecture:

apue$ cc -g -Wall -Werror -Wextra gdb2.c
apue$ gdb ./a.out
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
0x000076cd776d77ab in ?? () from /usr/lib/libc.so.12
(gdb) bt
#0  0x000076cd776d77ab in ?? () from /usr/lib/libc.so.12
#1  0x000076cd776c9781 in atoi () from /usr/lib/libc.so.12
#2  0x0000000000400a34 in main () at gdb2.c:14
(gdb) (gdb) frame 2
#2  0x0000000000400a34 in main () at gdb2.c:14
14              int num = atoi(getenv("BUFSIZ"));
(gdb)

Similarly, for your program, this should pinpoint
where in your code the problem occurred, and you can
then begin inspecting the different parameters.

If it fails calling 'fts_read(my_FTS_ptr)', I'd guess
that at that point 'my_FTS_ptr' is invalid?

The fact that it doesn't fail on Linux for you likely
has to do with other factors, such as different
invocation, different filesystem depth, or some such.

> My question, therefore, is if you know of any
> serious differences between NetBSD's fts.c and
> Linux's fts.c

FTS is part of the C library libc; NetBSD has its own
libc, while Linux uses GNU libc aka glibc.  It is
quite likely that the implementations of FTS differ.

Since both are open source, you can of course review
the code.  And using the 'ctags' example shown in
class, it's easy for you to find the code for at least
NetBSD's implementation:

- ensure you have the NetBSD source sets extracted in
  /usr/src
- run
  find /usr/src -name '*[ch]' -print | xargs ctags -f ~/.ctags
- run
  echo "set tags+=~/.ctags" >> ~/.vimrc

Once you have done that, any future desire to find the
implementation of the library functions you're dealing
with is trivial:

- open your source file
- place the cursor on the 'fts_open' function call
- Ctrl+]  now brings you to the source code
  implementation for this function, found under
  /usr/src/external/bsd/mdocml/dist/compat_fts.c

Or on the web at
http://cvsweb.netbsd.org/bsdweb.cgi/src/external/bsd/mdocml/dist/compat_fts.c?rev=HEAD&content-type=text/x-cvsweb-markup


For GNU glibc sources, go to
https://ftp.gnu.org/gnu/libc/ and fetch
https://ftp.gnu.org/gnu/libc/glibc-2.30.tar.xz,
extract, "find glibc-2.30 -name '*fts*' -print"
and then inspect glibs-2.30/io/fts.c

Note that this file includes the BSD copyright header,
suggesting that the GNU version is at least in part
derived from the BSD version, which explains the
strong similarities.

But I can virtually guarantee you that the problem is
not in the C library or the difference in the
implementation, but in your code. :-)

-Jan


More information about the cs631apue mailing list