By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,584 Members | 1,065 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,584 IT Pros & Developers. It's quick & easy.

passing array of structures to/from function

P: 10
Hello.

I'm pretty new to C, and having a problem which I suspect this has to do with how I'm handling (or not handling) pointers. I have an array of dirent structures which I am passing to a function. The function fills the structures with information on subdirectories in a given directory.

In the function itself, I can step through the array of structures and print to the console the list of directory names. However, when I try to do so from the calling program I get a Segmentation Fault. Snippets from my code are posted below.

Can you tell me what I'm doing wrong? Thanks!
Expand|Select|Wrap|Line Numbers
  1. #include <dirent.h>
  2.  
  3. int main(void)
  4. {
  5. struct dirent     **sEvents;        // structure containing event directory names
  6. int        iResult;        // return value
  7. int        iDirMax;        // number of event directories
  8. int        iDirCtr;        // directory counter
  9. int        GetDirectoryList();    // function to return list of directories
  10.  
  11. // get directory list
  12. iResult = GetDirectoryList(&sEvents, &iDirMax);
  13.  
  14. fprintf(stdout, "Number of Directories = %d\n", iDirMax);
  15.  
  16. for (iDirCtr = 0; iDirCtr < iDirMax; iDirCtr++)
  17.     {
  18.     // THIS GIVES Segmentation Fault..................................
  19.     fprintf(stdout, "Event Directory: %s\n", sEvents[iDirCtr]->d_name);
  20.     }
  21.  
  22. return 0;
  23. }
  24.  
  25. int GetDirectoryList(struct dirent **sEvents, int *iMax)
  26. {
  27. char        cSOD[512];        // path to parent directory
  28. int        iCtr;            // counter
  29.  
  30. // get the list of event directories
  31. *iMax = scandir (cSOD, &sEvents, DirFilter, alphasort);
  32. if (*iMax >= 0)
  33.     {
  34.     for (iCtr = 0; iCtr < *iMax; iCtr++)
  35.         {
  36.         // THIS PRINTS OK...........................................
  37.         fprintf(stdout, "EventDirectory %s\n", sEvents[iCtr]->d_name);
  38.         }
  39.     }
  40.  
  41. return 0;
  42. }
  43.  
  44.  
Jul 12 '07 #1
Share this Question
Share on Google+
13 Replies


weaknessforcats
Expert Mod 5K+
P: 9,197
struct dirent **sEvents; // structure containing event directory names
is not a structure. And it's not an array either. There is no array in your code.

sEvents is a pointer to a struct dirent pointer. You do not have a struct direct pointer so you can't initializae this sEvents variable.

I think you just need an array:
Expand|Select|Wrap|Line Numbers
  1. strict dirent myarray[100];
  2.  
  3. //and   then call your function:
  4.  
  5. GetDirectoryList(myarray, 100);
  6.  
  7. //where:
  8.  
  9. int GetDirectoryList(struct dirent *sEvents, int iMax)
  10. {
  11.      //in here sEvents[1] is the same as myarray[1]
  12. }
  13.  
Jul 12 '07 #2

P: 10
is not a structure. And it's not an array either. There is no array in your code.

sEvents is a pointer to a struct dirent pointer. You do not have a struct direct pointer so you can't initializae this sEvents variable.
Thanks for the quick reply. I'm sorry to be dense, but now I'm even more confused. I'll try to explain...

The scandir() function in my GetDirectoryList() function requires a pointer to a dirent pointer (that is, **dirent). scandir() uses malloc to allocate memory space for the set of dirent structures, fills those structures, and returns the number of structures. Therefore, as I understand it, after scandir() executes the **dirent pointer is a pointer to the starting place in memory for a set of pointers to the actual structures. Since I know how many structures there are, I can step through the directory names inside the GetDirectoryList() function using the syntax sEvents[n]->d_name. Any problems with my understanding/explanation so far?

Now the issue: in main() I declared the **dirent pointer, which after GetDirectoryList() executes I *think* should contain the pointer to the starting place in memory for the pointers to the dirent structures. But when I attempt in main() to step through the structures and extract the directory names using the same syntax as before (or any syntax I can think of), I get the Segmentation Fault.

So... where in the above is my understanding of the process breaking down?

Thanks again for all your help.
Jul 12 '07 #3

weaknessforcats
Expert Mod 5K+
P: 9,197
My problem now is that I don't know what GetDirectoryLIst() you are using. All of the sites for dirent.h do not contain this function and there of the may. many GetDirectoryList() functions I find, all of them require a patch as an argument and return a pointer to that folder.

There's nothing about filling an array.

Where are you getting this function from and where is it documented???
Jul 12 '07 #4

P: 10
GetDirectoryList() is the function I wrote -- see the original code snippet. In it I call the scandir() function, which is a Linux/Unix command.
Jul 12 '07 #5

weaknessforcats
Expert Mod 5K+
P: 9,197
I seem to be in the weeds and have misunderstood you. I apologize.

This code:

for (iDirCtr = 0; iDirCtr < iDirMax; iDirCtr++)
{
// THIS GIVES Segmentation Fault..................................
fprintf(stdout, "Event Directory: %s\n", sEvents[iDirCtr]->d_name);
}
This loop depends on iDirMax being correct from GetDirectoryList(). However, if GetDirectoryList() returns a 0 indicating an error, *iMax is not set to 0 so in the loop above you have garbage in iDirMax.

Change GetDirectoryList to return a void to force all checking to go through iMax (iDirMax in main()).
Jul 13 '07 #6

P: 10
Thanks so much for all your help! I finally figured out my problem:

struct dirent **sEvents was declared in main(); this is a pointer to a pointer to a structure.

I wanted the function GetDirectoryList() to fill the set of structures, so I had to pass the address to the pointer (&sEvents) to GetDirectoryList(), and declare it in GetDirectoryList() as struct dirent ***sEvents -- that is, a pointer to my original pointer.

Because I didn't have that 3rd level of dereferencing, I was never actually changing the contents of my original pointer.

Thanks again!
Jul 13 '07 #7

weaknessforcats
Expert Mod 5K+
P: 9,197
Wait a minute. Your GetDirectoryList() is:
Expand|Select|Wrap|Line Numbers
  1. int GetDirectoryList(struct dirent **sEvents, int *iMax)
  2. etc...\
  3.  
And your call is:
Expand|Select|Wrap|Line Numbers
  1. iResult = GetDirectoryList(&sEvents, &iDirMax);
  2.  
So if sEvents is a struct dirent **sEvents, then &sEvents is a struct dirent ***sEvents, which isn't what your function has as an argument. How are ytou getting this to compile?
Jul 14 '07 #8

P: 10
That's exactly my point. The gcc compiler didn't catch it, and it took me a week (and your and one other person's help) to figure it out.

I finally did it by filling my code with fprintf statements showing the memory addresses of various variables.
Jul 14 '07 #9

Expert 10K+
P: 11,448
That's exactly my point. The gcc compiler didn't catch it, and it took me a week (and your and one other person's help) to figure it out.
Did you use the -Wall flag for gcc? I'll warn about everything then.

I finally did it by filling my code with fprintf statements showing the memory addresses of various variables.
printf is the poor men's debugger and it is our friend ;-)

kind regards,

Jos
Jul 14 '07 #10

P: 10
Nope -- I didn't know about the -Wall flag. I will use it from now on... thanks for the tip!
Jul 15 '07 #11

Expert 10K+
P: 11,448
Nope -- I didn't know about the -Wall flag. I will use it from now on... thanks for the tip!
Read gcc's manual page; it has all sorts of nifty little flags that can reduce the
code size, speed thing up etc. etc. I always use that -Wall flag despite the
fact that gcc whines about a lot of things then, and I mean *a lot*. It does
improve your code quality though if you manage to keep gcc's mouth shut ;-)

kind regards,

Jos
Jul 15 '07 #12

P: 10
Well, I'm all for anything that will improve the quality of my code, especially when learning a new language. I'm also going to drop you a private message... please watch for it.

Thanks!
Jul 15 '07 #13

Expert 10K+
P: 11,448
Well, I'm all for anything that will improve the quality of my code, especially when learning a new language. I'm also going to drop you a private message... please watch for it.

Thanks!
I just replied.

kind regards,

Jos
Jul 15 '07 #14

Post your reply

Sign in to post your reply or Sign up for a free account.