d_name member of struct dirent

d_name member of struct dirent

Post by Sam Zoghai » Fri, 11 Jul 2003 03:31:26



Hello,

There is someting strange I've noticed when debugging code that use struct
dirent.
If you consider the follwing piece of code, which prints the name of all files
in the directory /home/foo

#include <dirent.h>
#include <stdio.h>

int main()
{
    struct dirent *dp;
    DIR *dfd;
    dfd = opendir("/home/foo);
    while ((dp = readdir(dfd)) != NULL)
        printf("%s\n", dp->d_name);
    return 0;

Quote:}

It works well (I haven't provided any error checking because it is not
relevant to my question) but if I set a breakpoint after dp has been
initialized, for instance, right before the call to printf and check the
value of dp->d_name, I get garbage.
Am I missing something?

Thank you,
Sam
--
"So if you meet me, have some courtesy, have some sympathy, and some taste
 Use all your well-learned politesse, or I'll lay your soul to waste"

    - The Rolling Stones, "Sympathy for the Devil"

 
 
 

d_name member of struct dirent

Post by Jens.Toerr.. » Fri, 11 Jul 2003 04:07:14



> There is someting strange I've noticed when debugging code that use struct
> dirent.
> If you consider the follwing piece of code, which prints the name of all files
> in the directory /home/foo
> #include <dirent.h>
> #include <stdio.h>
> int main()
> {
>     struct dirent *dp;
>     DIR *dfd;
>     dfd = opendir("/home/foo);
>     while ((dp = readdir(dfd)) != NULL)
>         printf("%s\n", dp->d_name);
>     return 0;
> }
> It works well (I haven't provided any error checking because it is not
> relevant to my question) but if I set a breakpoint after dp has been
> initialized, for instance, right before the call to printf and check the
> value of dp->d_name, I get garbage.
> Am I missing something?

Did you compile with optimization switched on? In this case it would
be possible (or even likely) that dp is kept in a register and the
"real" variable in memory you're looking at in the de* never
gets changed, only the register.
                                     Regards, Jens
--
      _  _____  _____

  _  | |  | |    | |
 | |_| |  | |    | |          http://www.veryComputer.com/~toerring
  \___/ens|_|homs|_|oerring

 
 
 

d_name member of struct dirent

Post by Sam Zoghai » Fri, 11 Jul 2003 04:12:20




comp.unix.programmer:

Quote:> Did you compile with optimization switched on?

No, I didn't.

Sam
--
"Fear is the path to the dark side.
 Fear leads to anger, anger leads to hatred, hatred leads to suffering.
 I sense much fear in you."

 
 
 

d_name member of struct dirent

Post by dbti » Fri, 11 Jul 2003 04:29:27



> Hello,

> There is someting strange I've noticed when debugging code that use struct
> dirent.
> If you consider the follwing piece of code, which prints the name of all files
> in the directory /home/foo

> #include <dirent.h>
> #include <stdio.h>

> int main()
> {
>     struct dirent *dp;
>     DIR *dfd;
>     dfd = opendir("/home/foo);
>     while ((dp = readdir(dfd)) != NULL)
>         printf("%s\n", dp->d_name);
>     return 0;
> }

> It works well (I haven't provided any error checking because it is not
> relevant to my question) but if I set a breakpoint after dp has been
> initialized, for instance, right before the call to printf and check the
> value of dp->d_name, I get garbage.
> Am I missing something?

> Thank you,
> Sam

It might be something as simple as you forgot to turn on the debugging
flag for your compilation.  That might cause odd results in what you're
seeing, based on where the de* thinks the instructions are for the
line you're trying to break on.

What compiler/de* suite are you using?

 
 
 

d_name member of struct dirent

Post by Sam Zoghai » Fri, 11 Jul 2003 05:10:59



Wednesday 09 July 2003 21:29 in comp.unix.programmer:

Quote:> It might be something as simple as you forgot to turn on the debugging
> flag for your compilation.  That might cause odd results in what you're
> seeing, based on where the de* thinks the instructions are for the
> line you're trying to break on.

No, I did not forget to turn debugging info on. In fact, that's the only
variable for which I get garbage.

Quote:> What compiler/de* suite are you using?

gcc (I tried 2.95, 3.0, 3.2 and 3.3) and the de* is gdb.

Sam
--
"Giving the Linus Torvalds Award to the Free Software Foundation is a bit like
giving the Han Solo Award to the Rebel Alliance"

        - Richard Stallman, August 1999

 
 
 

d_name member of struct dirent

Post by Jens.Toerr.. » Fri, 11 Jul 2003 07:54:02




> Wednesday 09 July 2003 21:29 in comp.unix.programmer:
>> It might be something as simple as you forgot to turn on the debugging
>> flag for your compilation.  That might cause odd results in what you're
>> seeing, based on where the de* thinks the instructions are for the
>> line you're trying to break on.
> No, I did not forget to turn debugging info on. In fact, that's the only
> variable for which I get garbage.
>> What compiler/de* suite are you using?
> gcc (I tried 2.95, 3.0, 3.2 and 3.3) and the de* is gdb.

What make you think that you get garbage? If I run your program under
gdb I get e.g. after the first call of readdir()

(gdb) n
10              printf("%s\n", dp->d_name);
(gdb) p dp
$1 = (struct dirent *) 0x80496c8
(gdb) p dp->d_name
$2 =
".\000\000\000\000\002\000\000\000\030\000\000\000\020\000\000..\000\000\00 000\000\000\030\000\000.Xresources\000\000\001\001\000P\000\000\000\020\000\000lab\000\000\005\b\000\000h\000\000\000
\000\000.bash_history\000\000\000\000\000\000\000\000\023\t\000\000x\000\000\000\030\000\000.bashrc\000\000\000\000\000\000\a\b\000\000\220\000\000\000
\000\000cperl-mode.el\000\000\000\000\000\000\000\000\202\t\000\000?\000\000\000\030\000\000.fvwm2rc\000\000\000\000\000\t\b\000"...

What you see here isn't garbage. When you have a look at the header file
/usr/include/bits/dirent.h where "struct dirent" is defined you will
find that the d_name member is defined as

    char d_name[256];       /* We must not include limits.h! */

So gdb isn't showing you the string only up to the first '\0' character
(as it would do for a char *) but all 256 chars that belong to d_name.
Perhaps that's why you think you're getting garbage?

                                     Regards, Jens
--
      _  _____  _____

  _  | |  | |    | |
 | |_| |  | |    | |          http://www.veryComputer.com/~toerring
  \___/ens|_|homs|_|oerring

 
 
 

d_name member of struct dirent

Post by Sam Zoghai » Fri, 11 Jul 2003 19:32:19




comp.unix.programmer:

Quote:> So gdb isn't showing you the string only up to the first '\0' character
> (as it would do for a char *) but all 256 chars that belong to d_name.
> Perhaps that's why you think you're getting garbage?

Ok, I see.
But why isn't dp->d_name

<name_of_entry_read>\000\000....

here, it seems it is more like:

<name_of_1st_entry>\000\000...<name_of_2nd_entry<\000....

I know it doesn't really matter, since we'll only read up to the first \000,
but the fact that the other entries' names appear mean that we can somehow
know the name of several files in directory (I guess up to 256 - n
characters, n being the number of files) with only one call to readdir(3). I
wonder how.

I realize I should not have called it garbage, since it probably led you to
think I got random character. I had noticed there were filenames in the
output of gdb, but did not notice that the chars up to the first \000 were
always the filename I was looking for. Sorry for the inaccuracy.

Thank you,
Sam
--
"Don't be afraid, I'm gonna give you the choice I never had..."

    - Lestat in "Interview with the Vampire" (Ann Rice, 1976)

 
 
 

d_name member of struct dirent

Post by David Schwart » Fri, 11 Jul 2003 19:56:06




Quote:> I know it doesn't really matter, since we'll only read up to the first
\000,
> but the fact that the other entries' names appear mean that we can somehow
> know the name of several files in directory (I guess up to 256 - n
> characters, n being the number of files) with only one call to readdir(3).
I
> wonder how.

    Until the system read the file name, it had no idea how big it was. So
it read more bytes than needed. This way, the next call to 'readdir' won't
require a real read (since the system already ready it).

    It also might just read the whole directory in one shot. Then it points
you at pieces of it as you call 'readdir'. If you think about it, what would
make the least sense is trying to actually read/parse the directory file by
file.

    DS

 
 
 

1. glibc 2 struct dirent header bug??

Hi,

I just moved some code from a Red Hat 4.1 system to a Red Hat 5.0
system(with glibc 2.0). I get a compilation error on some code that uses
opendir/readdir. Specifically, when trying to access the d_name field,
like:

struct dirent *entry;
/* opendir/readdir here */
char *name = entry->d_name;

The compiler barfs and says something to the effect of that I can't
dereference an imcompletly defined structure(error message is from
memory...).

I'm convinced this is a header bug(the code works on other systems
fine). Has anyone run into this and know how to fix it?

Thanks!
Mark

2. Memory use?

3. dirent struct in linux 1.12.53

4. Help! Internal Modem Problem

5. Alignment of members in structs

6. long file on NFS

7. what are the members of the inode struct?

8. 2 IP on the same nic

9. Getting "undefined struct/union member error" when trying to convert to 64bit code

10. glibc 2.0 accessing _cnt member in FILE struct (stdio.h)

11. FILE struct members in Linux

12. HELP: struct data members alignment???

13. Struct member: errno