Hi.
In the snippet of code below, I'm trying to understand why when the
struct dirent ** namelist
is declared with "file" scope, I don't have a problem freeing the
allocated memory. But when the struct is declared in main (block scope)
it will segfault when passing namelist to freeFileNames().
Since this seems to be just a matter of my understanding scope and
pointer parameter passing better, I only included what thought to be
relevant code. I'll happily provide compilable code if deemed necessary.
Please see commented lines:
struct dirent **namelist; /* file scope works */
int main(void)
{
/* struct dirent **namelist */ /* block scope doesn't work */
int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */
freeFileNames(namelist, n); /* included from mylib.h */
return 0;
}
Thank you very much for your comments,
Dieter 165 6732
Dieter wrote: Hi.
In the snippet of code below, I'm trying to understand why when the
struct dirent ** namelist
is declared with "file" scope, I don't have a problem freeing the allocated memory. But when the struct is declared in main (block scope) it will segfault when passing namelist to freeFileNames().
Since this seems to be just a matter of my understanding scope and pointer parameter passing better, I only included what thought to be relevant code. I'll happily provide compilable code if deemed necessary.
Please see commented lines:
struct dirent **namelist; /* file scope works */
int main(void) { /* struct dirent **namelist */ /* block scope doesn't work */ int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */ freeFileNames(namelist, n); /* included from mylib.h */
return 0; }
Thank you very much for your comments, Dieter
Here's the actual code if needed. Although dirent.h is platform
specific, I think my question is relative to standard C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#define H5DIR "/home/stella/data/h5/rawTables"
int getFileNames(char *directory, struct dirent **namelist);
int freeFileNames(struct dirent **namelist, int entries);
struct dirent **namelist;
int main(void)
{
int n;
n = getFileNames(H5DIR, namelist);
printf("%d\n",n);
err = freeFileNames(namelist, n);
if (err==0)
printf("There wasn't any files");
return 0;
}
int getFileNames(char *directory, struct dirent **namelist)
{
int n, i;
n = scandir(directory, &namelist, 0, alphasort);
if(n == -1){
perror("scandir returned: ");
exit(1);
}
if(n == 0){
printf("No files found. Quiting.\n\n");
exit(1);
}
for (i=0;i<n;i++){
printf("File: %s\n", namelist[i]->d_name);
}
return n;
}
int freeFileNames(struct dirent **namelist, int entries)
{
int i;
if (namelist == NULL)
return 0;
else{
printf("%d",entries);
for (i = 0; i < entries; i++){
free(namelist[i]);
namelist[i] = NULL;
printf("%d,", i);
}
puts("\n");
free(namelist);
namelist = NULL;
}
return 1;
}
On Thu, 05 Jan 2006 22:44:27 -0500, Dieter <us**********@comcast.net>
wrote in comp.lang.c: Dieter wrote: Hi.
In the snippet of code below, I'm trying to understand why when the
struct dirent ** namelist
is declared with "file" scope, I don't have a problem freeing the allocated memory. But when the struct is declared in main (block scope) it will segfault when passing namelist to freeFileNames().
Since this seems to be just a matter of my understanding scope and pointer parameter passing better, I only included what thought to be relevant code. I'll happily provide compilable code if deemed necessary.
Please see commented lines:
struct dirent **namelist; /* file scope works */
int main(void) { /* struct dirent **namelist */ /* block scope doesn't work */ int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */ freeFileNames(namelist, n); /* included from mylib.h */
return 0; }
Thank you very much for your comments, Dieter Here's the actual code if needed. Although dirent.h is platform specific, I think my question is relative to standard C.
The actual code is not needed, and is indeed off-topic. Your problem
has a great deal to do with how the function scandir(), which is
apparently from dirent.h, deals with pointers.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <errno.h>
#define H5DIR "/home/stella/data/h5/rawTables"
int getFileNames(char *directory, struct dirent **namelist); int freeFileNames(struct dirent **namelist, int entries);
struct dirent **namelist;
When you define this pointer a file scope, it has static storage
duration and is therefore initialized to NULL. When you define it
inside a function, it has automatic storage duration by default and it
not initialized at all.
int main(void) { int n;
n = getFileNames(H5DIR, namelist); printf("%d\n",n); err = freeFileNames(namelist, n); if (err==0) printf("There wasn't any files"); return 0; }
int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
[snip]
On the last line of code above, you pass a pointer to 'namelist'
(therefore a char ***) to scandir(). Presumably this function checks
whether the pointed-to char ** is NULL or not, and if it is NULL, it
allocates the necessary memory. And also presumably, if the
pointed-to char ** is not NULL, it assumes that it points to valid
memory and uses it. At the end you try to free a pointer that was not
allocated.
I would suggest that you study the documentation for the function
scandir() and see what the requirements are for that parameter.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jack Klein wrote: On Thu, 05 Jan 2006 22:44:27 -0500, Dieter <us**********@comcast.net> wrote in comp.lang.c:
Dieter wrote:
Hi.
In the snippet of code below, I'm trying to understand why when the
struct dirent ** namelist
is declared with "file" scope, I don't have a problem freeing the allocated memory. But when the struct is declared in main (block scope) it will segfault when passing namelist to freeFileNames().
Since this seems to be just a matter of my understanding scope and pointer parameter passing better, I only included what thought to be relevant code. I'll happily provide compilable code if deemed necessary.
Please see commented lines:
struct dirent **namelist; /* file scope works */
int main(void) { /* struct dirent **namelist */ /* block scope doesn't work */ int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */ freeFileNames(namelist, n); /* included from mylib.h */
return 0; }
Thank you very much for your comments, Dieter
Here's the actual code if needed. Although dirent.h is platform specific, I think my question is relative to standard C.
The actual code is not needed, and is indeed off-topic. Your problem has a great deal to do with how the function scandir(), which is apparently from dirent.h, deals with pointers. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <errno.h>
#define H5DIR "/home/stella/data/h5/rawTables"
int getFileNames(char *directory, struct dirent **namelist); int freeFileNames(struct dirent **namelist, int entries);
struct dirent **namelist;
When you define this pointer a file scope, it has static storage duration and is therefore initialized to NULL. When you define it inside a function, it has automatic storage duration by default and it not initialized at all.
int main(void) { int n;
n = getFileNames(H5DIR, namelist); printf("%d\n",n); err = freeFileNames(namelist, n); if (err==0) printf("There wasn't any files"); return 0; }
int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
[snip]
On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated.
I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter.
Jack, I sincerely thank you for commenting.
NULL initialization was certainly an issue.
Dieter
Dieter wrote: Jack Klein wrote:
[snip]
On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated.
I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter.
Jack, I sincerely thank you for commenting.
NULL initialization was certainly an issue.
All of which points out why we want queries to be topical. Once
you involve an unknown header (dirent) and an unknown function
(scandir) nobody can have any accurate idea what goes on. This is
why this whole thread should have been on a newsgroup dealing with
your system in the first place.
The fact that Jack could make an educated guess does not affect
this. His guess could well have been total nonsense, and could
have missed important factors. There is (in principle) noone here
to correct any mistakes.
--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
sorry if thjis is a duplicate reply...
I guess this is a scope issue for variable "namelist"
I suggest to change the function
int getFileName(char *,struct dirent ***);
and make necessary changes to code.
it may work fine
bcoz scandir i guess sets "struct dirent **" itself.
if its global all is fine, but local variables 0 its problem-same as
pass by value
thanks
-M.B
please check
pass by value
v/s pass by ref/pointers carefully
hope this helps to solve the issue
In article <SZ******************************@comcast.com>
Dieter <us**********@comcast.net> wrote: struct dirent **namelist; /* file scope works */
int main(void) { /* struct dirent **namelist */ /* block scope doesn't work */ int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */
This passes the *value* of the variable "namelist" to the function.
If namelist has block scope, the variable is also automatic, and hence
uninitialized, and hence contains garbage. If namelist has file
scope, the variable also has static duration and hence is
initialized to NULL.
In any case, getFileNames() cannot change the value stored in
the variable named "namelist" (unless it does not declare one
of its own, and does access the file-scope one). So it makes
no sense to pass the value in the first place, if namelist is
a block-scope variable.
If getFileNames() needs to modify namelist, it will need the
address of the variable:
extern int getFileNames(first_type, struct dirent ***);
...
int main(void) {
struct dirent **namelist;
int n;
/* optional: namelist = NULL; */
n = getFileNames(H5DIR, &namelist);
freeFileNames(namelist, n); /* included from mylib.h */
Presumably the NULL-initialized file-scope static-duration version
causes freeFileNames() to be a no-op. Passing the uninitialized
value of the block-scope version presumably does not.
return 0; }
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Chuck F. wrote: Dieter wrote:
Jack Klein wrote:
[snip]
On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated.
I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter.
Jack, I sincerely thank you for commenting.
NULL initialization was certainly an issue.
All of which points out why we want queries to be topical. Once you involve an unknown header (dirent) and an unknown function (scandir) nobody can have any accurate idea what goes on. This is why this whole thread should have been on a newsgroup dealing with your system in the first place.
The fact that Jack could make an educated guess does not affect this. His guess could well have been total nonsense, and could have missed important factors. There is (in principle) noone here to correct any mistakes.
Yes I appreciate that.
My question, I believed, was standard C specific and debated whether to
post it here. In the future *anything* including anything other than
standard C will be posted elsewhere.
Possibly the newsgroup's name could be changed to comp.lang.C.standard,
or some such. It might eliminate a small amount of the regular grief you
all encounter.
Regards,
Dieter
M.B wrote: please check pass by value v/s pass by ref/pointers carefully
hope this helps to solve the issue
Thank you for your comments MB.
Dieter wrote: Hi.
In the snippet of code below, I'm trying to understand why when the
struct dirent ** namelist
is declared with "file" scope, I don't have a problem freeing the allocated memory. But when the struct is declared in main (block scope) it will segfault when passing namelist to freeFileNames().
Since this seems to be just a matter of my understanding scope and pointer parameter passing better, I only included what thought to be relevant code. I'll happily provide compilable code if deemed necessary.
Please see commented lines:
struct dirent **namelist; /* file scope works */
int main(void) { /* struct dirent **namelist */ /* block scope doesn't work */ int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */ freeFileNames(namelist, n); /* included from mylib.h */
return 0; }
Thank you very much for your comments, Dieter
My apologies to the regulars for an OT inclusion related to the question.
< This Thread Closed >
Thanks,
Dieter
Chris Torek wrote: In article <SZ******************************@comcast.com> Dieter <us**********@comcast.net> wrote:
struct dirent **namelist; /* file scope works */
int main(void) { /* struct dirent **namelist */ /* block scope doesn't work */ int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */
This passes the *value* of the variable "namelist" to the function. If namelist has block scope, the variable is also automatic, and hence uninitialized, and hence contains garbage. If namelist has file scope, the variable also has static duration and hence is initialized to NULL.
In any case, getFileNames() cannot change the value stored in the variable named "namelist" (unless it does not declare one of its own, and does access the file-scope one). So it makes no sense to pass the value in the first place, if namelist is a block-scope variable.
If getFileNames() needs to modify namelist, it will need the address of the variable:
extern int getFileNames(first_type, struct dirent ***); ... int main(void) { struct dirent **namelist; int n;
/* optional: namelist = NULL; */ n = getFileNames(H5DIR, &namelist);
freeFileNames(namelist, n); /* included from mylib.h */
Presumably the NULL-initialized file-scope static-duration version causes freeFileNames() to be a no-op. Passing the uninitialized value of the block-scope version presumably does not.
return 0; }
You've hit the nail on the head. That's exactly what I've been having
trouble wrapping my mind around.
* Pass the address of the pointer in order to return it's value modified. *
The N indirection, dynamic allocation, and passing them has been
confusing me.
Thanks Chris
Dieter wrote: Jack Klein wrote: On Thu, 05 Jan 2006 22:44:27 -0500, Dieter <us**********@comcast.net> wrote in comp.lang.c:
Dieter wrote:
Hi.
In the snippet of code below, I'm trying to understand why when the
struct dirent ** namelist
is declared with "file" scope, I don't have a problem freeing the allocated memory. But when the struct is declared in main (block scope) it will segfault when passing namelist to freeFileNames().
Since this seems to be just a matter of my understanding scope and pointer parameter passing better, I only included what thought to be
relevant code. I'll happily provide compilable code if deemed necessary.
Please see commented lines:
struct dirent **namelist; /* file scope works */
int main(void) { /* struct dirent **namelist */ /* block scope doesn't work */ int n;
n = getFileNames(H5DIR, namelist); /* included from mylib.h */ freeFileNames(namelist, n); /* included from mylib.h */
return 0; }
Thank you very much for your comments, Dieter
Here's the actual code if needed. Although dirent.h is platform specific, I think my question is relative to standard C.
The actual code is not needed, and is indeed off-topic. Your problem has a great deal to do with how the function scandir(), which is apparently from dirent.h, deals with pointers. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <errno.h>
#define H5DIR "/home/stella/data/h5/rawTables"
int getFileNames(char *directory, struct dirent **namelist); int freeFileNames(struct dirent **namelist, int entries);
struct dirent **namelist;
When you define this pointer a file scope, it has static storage duration and is therefore initialized to NULL. When you define it inside a function, it has automatic storage duration by default and it not initialized at all.
int main(void) { int n;
n = getFileNames(H5DIR, namelist); printf("%d\n",n); err = freeFileNames(namelist, n); if (err==0) printf("There wasn't any files"); return 0; }
int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
[snip]
On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated.
I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter.
Jack, I sincerely thank you for commenting.
NULL initialization was certainly an issue.
Dieter
I guess this is a scope issue for variable "namelist"
I suggest to change the function
int getFileName(char *,struct dirent ***);
and make necessary changes to code.
it may work fine
bcoz scandir i guess sets "struct dirent **" itself.
if its global all is fine, but local variables 0 its problem-same as
pass by value
thanks
-M.B
please chanmge function int getFileName(char *,struct dirent **);
to int getFileNames(char *,struct dirent ***) and make necessary
changes to code to accomodate this
its a pass by value v/s pass by reference issue
This works without segfault.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#define H5DIR "./"
int getFileNames(char *directory, struct dirent ***namelist);
int freeFileNames(struct dirent **namelist, int entries);
int main(void)
{
int n,err;
struct dirent **namelist;
n = getFileNames(H5DIR,&namelist);
printf("%d\n",n);
err = freeFileNames(namelist, n);
if (err==0)
printf("There wasn't any files");
return 0;
}
int getFileNames(char *directory, struct dirent ***namelist)
{
int n, i;
n = scandir(directory, namelist, 0, alphasort);
if(n == -1){
perror("scandir returned: ");
exit(1);
}
if(n == 0){
printf("No files found. Quiting.\n\n");
exit(1);
}
for (i=0;i<n;i++){
printf("File: %s\n", (*namelist)[i]->d_name);
}
return n;
}
int freeFileNames(struct dirent **namelist, int entries)
{
int i;
if (namelist == NULL)
return 0;
else{
printf("%d",entries);
for (i = 0; i < entries; i++){
free(namelist[i]);
namelist[i] = NULL;
printf("%d,", i);
}
puts("\n");
free(namelist);
namelist = NULL;
}
return 1;
}
Chuck F. wrote: Dieter wrote: Jack Klein wrote:
[snip]
On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated.
I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter. Jack, I sincerely thank you for commenting.
NULL initialization was certainly an issue.
All of which points out why we want queries to be topical. Once you involve an unknown header (dirent) and an unknown function (scandir) nobody can have any accurate idea what goes on. This is why this whole thread should have been on a newsgroup dealing with your system in the first place.
btw dirent or dirent.h is not alien. its of course not in ansi but in
posix (k&r also mentions it)
The fact that Jack could make an educated guess does not affect this. His guess could well have been total nonsense, and could have missed important factors. There is (in principle) noone here to correct any mistakes.
I agree here. Anyone replying here want to help in any case. But we all
can help in giving suggestions but not spoonfeed. I may not know what
others know . knowlegde sharing is the idea here.
-- "If you want to post a followup via groups.google.com, don't use the broken "Reply" link at the bottom of the article. Click on "show options" at the top of the article, then click on the "Reply" at the bottom of the article headers." - Keith Thompson More details at: <http://cfaj.freeshell.org/google/>
Chuck F. wrote: Dieter wrote: Jack Klein wrote:
[snip]
On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated.
I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter. Jack, I sincerely thank you for commenting.
NULL initialization was certainly an issue.
All of which points out why we want queries to be topical. Once you involve an unknown header (dirent) and an unknown function (scandir) nobody can have any accurate idea what goes on. This is why this whole thread should have been on a newsgroup dealing with your system in the first place.
btw dirent or dirent.h is not alien. its of course not in ansi but in
posix (k&r also mentions it)
The fact that Jack could make an educated guess does not affect this. His guess could well have been total nonsense, and could have missed important factors. There is (in principle) noone here to correct any mistakes.
I agree here. Anyone replying here want to help in any case. But we all
can help in giving suggestions but not spoonfeed. I may not know what
others know . knowlegde sharing is the idea here.
-- "If you want to post a followup via groups.google.com, don't use the broken "Reply" link at the bottom of the article. Click on "show options" at the top of the article, then click on the "Reply" at the bottom of the article headers." - Keith Thompson More details at: <http://cfaj.freeshell.org/google/>
M.B wrote: This works without segfault. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <errno.h>
#define H5DIR "./"
int getFileNames(char *directory, struct dirent ***namelist); int freeFileNames(struct dirent **namelist, int entries);
int main(void) { int n,err; struct dirent **namelist;
n = getFileNames(H5DIR,&namelist); printf("%d\n",n); err = freeFileNames(namelist, n); if (err==0) printf("There wasn't any files"); return 0;
}
int getFileNames(char *directory, struct dirent ***namelist) { int n, i;
n = scandir(directory, namelist, 0, alphasort); if(n == -1){ perror("scandir returned: "); exit(1); } if(n == 0){ printf("No files found. Quiting.\n\n"); exit(1); } for (i=0;i<n;i++){ printf("File: %s\n", (*namelist)[i]->d_name); }
return n;
}
int freeFileNames(struct dirent **namelist, int entries) { int i;
if (namelist == NULL) return 0; else{ printf("%d",entries); for (i = 0; i < entries; i++){ free(namelist[i]); namelist[i] = NULL; printf("%d,", i); } puts("\n"); free(namelist); namelist = NULL; }
return 1; }
MB, I can't express enough how much I appreciate your contribution.
Thank you for taking the time... and bending the sacred rules a little. :)
"Chuck F. " <cb********@yahoo.com> writes: Dieter wrote: Jack Klein wrote: [snip] On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated. I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter. Jack, I sincerely thank you for commenting. NULL initialization was certainly an issue.
All of which points out why we want queries to be topical. Once you involve an unknown header (dirent) and an unknown function (scandir) nobody can have any accurate idea what goes on. This is why this whole thread should have been on a newsgroup dealing with your system in the first place.
The fact that Jack could make an educated guess does not affect this. His guess could well have been total nonsense, and could have missed important factors. There is (in principle) noone here to correct any mistakes.
In this case, there wasn't really any need to guess. The code causing
the problem was:
struct dirent **namelist;
int n;
n = getFileNames(H5DIR, namelist);
It might as well have been:
struct foo **bar;
int n;
n = bleeble(blah, bar);
Regardless of what struct dirent/struct foo is, and regardless of what
getFileNames() or bleeble() does with its arguments, passing an
uninitialized variable to a function is almost certainly an error.
(Come to think of it, drop the "almost".)
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dieter wrote: int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
Hi,
As other groups members has remarked, the problem was in the call to
scandir (the program doesn't works if the variable is global and also
doesn't works if it is local. The only diference is how bad are the
effects).
I want only to remark two things about modify a function parameter:
a) The changes done to the value of a parameter will be always lost at
function return.
b) Change a parameter is under stylistic discussion (in particular, I
never do it. If necessary, I declare a local and init it with the
parameter value), and, who knows if allowed by standard. By example, a
SPARC CPU uses registers to pass parameters, so, the address of a
parameter is something that breaks to normal function prologs
(assembler code at start of fucntion).
In conclusion, any line of the kind "¶meter" must be carefully
reviewed.
Kind regards.
M.B said: its a pass by value v/s pass by reference issue
Since C doesn't have pass by reference, it is clear to me that you are
talking nonsense.
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Keith Thompson wrote: "Chuck F. " <cb********@yahoo.com> writes: Dieter wrote: Jack Klein wrote: [snip] On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it. At the end you try to free a pointer that was not allocated. I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter. Jack, I sincerely thank you for commenting. NULL initialization was certainly an issue. All of which points out why we want queries to be topical. Once you involve an unknown header (dirent) and an unknown function (scandir) nobody can have any accurate idea what goes on. This is why this whole thread should have been on a newsgroup dealing with your system in the first place.
The fact that Jack could make an educated guess does not affect this. His guess could well have been total nonsense, and could have missed important factors. There is (in principle) noone here to correct any mistakes.
In this case, there wasn't really any need to guess. The code causing the problem was:
struct dirent **namelist; int n; n = getFileNames(H5DIR, namelist);
It might as well have been:
struct foo **bar; int n; n = bleeble(blah, bar);
Regardless of what struct dirent/struct foo is, and regardless of what getFileNames() or bleeble() does with its arguments, passing an uninitialized variable to a function is almost certainly an error. (Come to think of it, drop the "almost".)
Why do we initialize the variable if the variable is it is being
returned by the called function with a valid value
for ex
void f(int *i)
{
*i=1;
return;
}
int main(void)
{
int k; /*why need int k=0... */
f(&k);
...
return(0);
}
------------------
related
----------------------
void f(int i) /* I intend to modify i */
{
i=1;
return;
}
int main(void)
{
int k=0; /*why need int k=0... */
f(k);
...
return(0);
}
No effect on variable "k"
what initialization (0) helps in this case -- Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst> We must do something. This is something. Therefore, we must do this.
- M.B
tmp123 wrote: Dieter wrote:
int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
Hi,
As other groups members has remarked, the problem was in the call to scandir (the program doesn't works if the variable is global and also doesn't works if it is local. The only diference is how bad are the effects).
I want only to remark two things about modify a function parameter: a) The changes done to the value of a parameter will be always lost at function return. b) Change a parameter is under stylistic discussion (in particular, I never do it. If necessary, I declare a local and init it with the parameter value),
Hi tmp,
Hmm, this last point you made is not quite clear to me. My goal is to
try to localize/modularize most of what I can and dynamic
allocation~value passing will also be necessarily frequent (I think)
considering event driven considerations. I don't see how I'd be able to
avoid it.
Thanks for your commenting,
Dieter
and, who knows if allowed by standard. By example, a SPARC CPU uses registers to pass parameters, so, the address of a parameter is something that breaks to normal function prologs (assembler code at start of fucntion).
In conclusion, any line of the kind "¶meter" must be carefully reviewed.
Kind regards.
M.B wrote: sorry if thjis is a duplicate reply...
I guess this is a scope issue for variable "namelist" I suggest to change the function int getFileName(char *,struct dirent ***); and make necessary changes to code. it may work fine
bcoz scandir i guess sets "struct dirent **" itself. if its global all is fine, but local variables 0 its problem-same as pass by value
Please use English, not dudespeak, in this newsgroup, and include
adequate context. Between the two your article is totally
meaningless. See below for further advice.
--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Dieter wrote: tmp123 wrote: Dieter wrote:
int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
Hi,
As other groups members has remarked, the problem was in the call to scandir (the program doesn't works if the variable is global and also doesn't works if it is local. The only diference is how bad are the effects).
I want only to remark two things about modify a function parameter: a) The changes done to the value of a parameter will be always lost at function return. b) Change a parameter is under stylistic discussion (in particular, I never do it. If necessary, I declare a local and init it with the parameter value),
Hi tmp,
Hmm, this last point you made is not quite clear to me. My goal is to try to localize/modularize most of what I can and dynamic allocation~value passing will also be necessarily frequent (I think) considering event driven considerations. I don't see how I'd be able to avoid it.
Thanks for your commenting, Dieter
and, who knows if allowed by standard. By example, a SPARC CPU uses registers to pass parameters, so, the address of a parameter is something that breaks to normal function prologs (assembler code at start of fucntion).
In conclusion, any line of the kind "¶meter" must be carefully reviewed.
Kind regards.
Sorry, it is my fault, I've not been clear enough:
Some examples:
void foo(int *a)
{
*a=14;
}
void test ( int a )
{
int b;
b=2; /* 1: of course, OK */
a=2; /* 2: probably OK, but I do not know if according statndard, and
only in my personal style, not nice */
foo(&b); /* 3: OK */
foo(&a); /* 4: same than 2. In additon, dangerous in the sense that
it is
easy to thing that "a" will be modified afetr
return. Moreover, in some
machines "a" is stored in a register, so, &a
causes an small dificulty */
}
Is point 4 the one that, I do not say wrong, but I suggest to verify
carefully. In fact, one line like this one is the origin of the problem
in your post.
Kind regards.
tmp123 wrote: Dieter wrote: tmp123 wrote: Dieter wrote:
>int getFileNames(char *directory, struct dirent **namelist) >{ > int n, i; > > n = scandir(directory, &namelist, 0, alphasort);
Hi,
As other groups members has remarked, the problem was in the call to scandir (the program doesn't works if the variable is global and also doesn't works if it is local. The only diference is how bad are the effects).
I want only to remark two things about modify a function parameter: a) The changes done to the value of a parameter will be always lost at function return. b) Change a parameter is under stylistic discussion (in particular, I never do it. If necessary, I declare a local and init it with the parameter value), Hi tmp,
Hmm, this last point you made is not quite clear to me. My goal is to try to localize/modularize most of what I can and dynamic allocation~value passing will also be necessarily frequent (I think) considering event driven considerations. I don't see how I'd be able to avoid it.
Thanks for your commenting, Dieter
and, who knows if allowed by standard. By example, a SPARC CPU uses registers to pass parameters, so, the address of a parameter is something that breaks to normal function prologs (assembler code at start of fucntion).
In conclusion, any line of the kind "¶meter" must be carefully reviewed.
Kind regards.
Sorry, it is my fault, I've not been clear enough:
Some examples:
void foo(int *a) { *a=14; }
void test ( int a ) { int b; b=2; /* 1: of course, OK */ a=2; /* 2: probably OK, but I do not know if according statndard, and only in my personal style, not nice */ foo(&b); /* 3: OK */ foo(&a); /* 4: same than 2. In additon, dangerous in the sense that it is
Sorry if i did'nt get you
But why would anyone ever write such a construct
In this case "a" could as well be a local var in test
bcoz after return from test (to main or somewhere) anyway parameter to
test remains unchanged
easy to thing that "a" will be modified afetr return. Moreover, in some machines "a" is stored in a register, so, &a causes an small dificulty */ }
Is point 4 the one that, I do not say wrong, but I suggest to verify carefully. In fact, one line like this one is the origin of the problem in your post.
Kind regards.
M.B wrote
(in article
<11*********************@z14g2000cwz.googlegroups. com>): All of which points out why we want queries to be topical. Once you involve an unknown header (dirent) and an unknown function (scandir) nobody can have any accurate idea what goes on. This is why this whole thread should have been on a newsgroup dealing with your system in the first place. btw dirent or dirent.h is not alien. its of course not in ansi but in posix (k&r also mentions it)
It most certainly is alien to those not using a POSIX platform,
and IIRC, it pre-dates POSIX. Even so, there is no guarantee
that a standard conforming C compiler and linker will no a thing
about it. That's the whole point. The fact that Jack could make an educated guess does not affect this. His guess could well have been total nonsense, and could have missed important factors. There is (in principle) noone here to correct any mistakes.
I agree here. Anyone replying here want to help in any case. But we all can help in giving suggestions but not spoonfeed. I may not know what others know . knowlegde sharing is the idea here.
No, the issue raised was that if someone asks a question about a
nonstandard extension that is rarely seen, or at least not by
the regulars, then any responses offered could be complete
bullschildt, yet go undetected. When you ask a question in a
forum populated by people that specialize on the topic, you get
much better (and peer reviewed) answers. When you ask a
question on GPS navigation in comp.graphics.apps.photoshop, no
telling what will happen.
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw
How 'bout them Horns?
On 2006-01-06, Jack Klein <ja*******@spamcop.net> wrote: On Thu, 05 Jan 2006 22:44:27 -0500, Dieter <us**********@comcast.net> wrote in comp.lang.c:
Dieter wrote: > Hi. > > In the snippet of code below, I'm trying to understand why when the > > struct dirent ** namelist > > is declared with "file" scope, I don't have a problem freeing the > allocated memory. But when the struct is declared in main (block scope) > it will segfault when passing namelist to freeFileNames(). > > Since this seems to be just a matter of my understanding scope and > pointer parameter passing better, I only included what thought to be > relevant code. I'll happily provide compilable code if deemed necessary. > > Please see commented lines: > > > struct dirent **namelist; /* file scope works */ > > int main(void) > { > /* struct dirent **namelist */ /* block scope doesn't work */ > int n; > > n = getFileNames(H5DIR, namelist); /* included from mylib.h */ > freeFileNames(namelist, n); /* included from mylib.h */ > > return 0; > } > > > Thank you very much for your comments, > Dieter Here's the actual code if needed. Although dirent.h is platform specific, I think my question is relative to standard C.
The actual code is not needed, and is indeed off-topic. Your problem has a great deal to do with how the function scandir(), which is apparently from dirent.h, deals with pointers.
scandir(const char *dirname, struct dirent ***namelist, int
(*select)(struct dirent *), int (*compar)(const void *, const void *));
According to the the manpage, it appears to build an array of pointer to
struct dirent, the with the array of pointers and the object pointed to
by each pointer being from malloc(). It then stores the "array" [i.e.
first level of malloc pointer] in *namelist. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <errno.h>
#define H5DIR "/home/stella/data/h5/rawTables"
int getFileNames(char *directory, struct dirent **namelist); int freeFileNames(struct dirent **namelist, int entries);
struct dirent **namelist;
When you define this pointer a file scope, it has static storage duration and is therefore initialized to NULL. When you define it inside a function, it has automatic storage duration by default and it not initialized at all.
int main(void) { int n;
n = getFileNames(H5DIR, namelist); printf("%d\n",n); err = freeFileNames(namelist, n); if (err==0) printf("There wasn't any files"); return 0; }
int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
[snip]
On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it.
My understanding of the manpage on my implementation, backed up by my
reading of the source on my particular implementation, is that it
ignores any previously-pointed-to value and only stores to *namelist.
[why are you calling 'struct dirent' 'char'?]
At the end you try to free a pointer that was not allocated.
You snipped this part, so I can't comment on it. According to the
manpage, you are supposed to free each member of *namelist [individual
struct dirent *] in turn, then free *namelist. The question is, what
differs between his two versions?
I would suggest that you study the documentation for the function scandir() and see what the requirements are for that parameter.
On 2006-01-06, Richard Heathfield <in*****@invalid.invalid> wrote: M.B said:
its a pass by value v/s pass by reference issue
Since C doesn't have pass by reference, it is clear to me that you are talking nonsense.
"pass by reference", in common usage, can also apply to the practice
(common in C and appearing several places in the standard library) of
passing a pointer to a value intended to be stored into, rather than any
alternate calling convention specifically supported by the language
"M.B" <mb*******@gmail.com> writes: Keith Thompson wrote:
[...] In this case, there wasn't really any need to guess. The code causing the problem was:
struct dirent **namelist; int n; n = getFileNames(H5DIR, namelist);
It might as well have been:
struct foo **bar; int n; n = bleeble(blah, bar);
Regardless of what struct dirent/struct foo is, and regardless of what getFileNames() or bleeble() does with its arguments, passing an uninitialized variable to a function is almost certainly an error. (Come to think of it, drop the "almost".)
Why do we initialize the variable if the variable is it is being returned by the called function with a valid value
Because evaluating an uninitialized variable, whether by using it as a
function argument or in some other expression, invokes undefined
behavior.
for ex void f(int *i) { *i=1; return; }
int main(void) { int k; /*why need int k=0... */ f(&k); ... return(0); }
That's not the same thing. There's no need to initialize k, because
you're not passing the value of k to f(); you're merely passing its
address. Within f(), the value of *i is uninitialized garbage, but
that's ok because it doesn't attempt to read it. The value of i is a
valid address (specifically the address of main's k), so there's no
problem referring to i.
------------------ related ---------------------- void f(int i) /* I intend to modify i */ { i=1; return; }
int main(void) { int k=0; /*why need int k=0... */ f(k); ... return(0); }
No effect on variable "k" what initialization (0) helps in this case
This f() function is very strangely written. The first thing it does
is assign a value to its parameter, losing whatever value was passed
in by the caller. It would make more sense to declare "void f(void)"
and make i a local variable.
For a realistic function f() that uses the value of its parameter, it
wouldn't make sense to call it with an uninitialized value. Even with
f() as written, if you changed "int k=0;" to "int k;", just evaluating
the value of k invokes undefined behavior. In practice, this is
unlikely to cause any visible symptoms; type int typically doesn't
have any trap representations. You are likely, however, to get a
warning from the compiler. -- Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst> We must do something. This is something. Therefore, we must do this.
When you post a followup, please delete any quoted text that isn't
relevant. In particular, don't quote a signature unless you're
actually commenting on the signature. (Deletions are typically marked
with "[...]" or "[snip]".)
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
"tmp123" <tm****@menta.net> writes: Dieter wrote: int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort); As other groups members has remarked, the problem was in the call to scandir (the program doesn't works if the variable is global and also doesn't works if it is local. The only diference is how bad are the effects).
The variable in question was a pointer which is passed to a function.
If it's global, it's initialized to a null pointer value, which could
be a perfectly valid value for that argument. Whether this is
actually the case depends on the details of the non-standard function
scandir().
I want only to remark two things about modify a function parameter: a) The changes done to the value of a parameter will be always lost at function return. b) Change a parameter is under stylistic discussion (in particular, I never do it. If necessary, I declare a local and init it with the parameter value), and, who knows if allowed by standard. By example, a SPARC CPU uses registers to pass parameters, so, the address of a parameter is something that breaks to normal function prologs (assembler code at start of fucntion).
In conclusion, any line of the kind "¶meter" must be carefully reviewed.
A parameter is effectively a local variable, initialized to the value
given in the call. Taking its address is no more problematic that
taking the address of any other local variable. The fact that it may
have been passed in a register is irrelevant; if you take and use its
address, the compiler *must* store it in memory somewhere.
I tend to agree with you about the style issue of not modifying the
value of a parameter within a function. If I see a reference to a
parameter within a function, I tend to assume that it refers to the
value that was passed by the caller; if the function modifies it,
understanding the function requires a more complex mental model. But
this is at least partly because I've spent a lot of time working in a
language that makes parameters constant by default; I think that was a
good idea from a language design point of view, but it's not what C
does. In C, as I said, a parameter is really just a local variable,
and as a *reader* of C you have to be prepared to deal with code that
treats it as a variable.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Keith Thompson wrote: "tmp123" <tm****@menta.net> writes:
Dieter wrote:
int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
As other groups members has remarked, the problem was in the call to scandir (the program doesn't works if the variable is global and also doesn't works if it is local. The only diference is how bad are the effects).
The variable in question was a pointer which is passed to a function. If it's global, it's initialized to a null pointer value, which could be a perfectly valid value for that argument. Whether this is actually the case depends on the details of the non-standard function scandir().
I want only to remark two things about modify a function parameter: a) The changes done to the value of a parameter will be always lost at function return. b) Change a parameter is under stylistic discussion (in particular, I never do it. If necessary, I declare a local and init it with the parameter value), and, who knows if allowed by standard. By example, a SPARC CPU uses registers to pass parameters, so, the address of a parameter is something that breaks to normal function prologs (assembler code at start of fucntion).
In conclusion, any line of the kind "¶meter" must be carefully reviewed.
A parameter is effectively a local variable, initialized to the value given in the call. Taking its address is no more problematic that taking the address of any other local variable. The fact that it may have been passed in a register is irrelevant; if you take and use its address, the compiler *must* store it in memory somewhere.
I tend to agree with you about the style issue of not modifying the value of a parameter within a function. If I see a reference to a parameter within a function, I tend to assume that it refers to the value that was passed by the caller; if the function modifies it, understanding the function requires a more complex mental model. But this is at least partly because I've spent a lot of time working in a language that makes parameters constant by default; I think that was a good idea from a language design point of view, but it's not what C does. In C, as I said, a parameter is really just a local variable, and as a *reader* of C you have to be prepared to deal with code that treats it as a variable.
Hi Kieth, thank you for your comments.
So if I understand correctly, It's advisable, that when passing a
pointer in the paramater of a called function (that needs to be modified
for the originating (calling) scope, /for example/ ), that the paramater
(passed pointer) should then be pointed to by a local pointer variable
in the called function. This then makes *clear* the individuality
between the original value being passed and the modification of that
value, and is then,in effect, modifying the value in the calling scope.
Dieter
Dieter <us**********@comcast.net> writes: Keith Thompson wrote:
[...] A parameter is effectively a local variable, initialized to the value given in the call. Taking its address is no more problematic that taking the address of any other local variable. The fact that it may have been passed in a register is irrelevant; if you take and use its address, the compiler *must* store it in memory somewhere. I tend to agree with you about the style issue of not modifying the value of a parameter within a function. If I see a reference to a parameter within a function, I tend to assume that it refers to the value that was passed by the caller; if the function modifies it, understanding the function requires a more complex mental model. But this is at least partly because I've spent a lot of time working in a language that makes parameters constant by default; I think that was a good idea from a language design point of view, but it's not what C does. In C, as I said, a parameter is really just a local variable, and as a *reader* of C you have to be prepared to deal with code that treats it as a variable.
Hi Kieth, thank you for your comments.
It's "Keith".
So if I understand correctly, It's advisable, that when passing a pointer in the paramater of a called function (that needs to be modified for the originating (calling) scope, /for example/ ), that the paramater (passed pointer) should then be pointed to by a local pointer variable in the called function. This then makes *clear* the individuality between the original value being passed and the modification of that value, and is then,in effect, modifying the value in the calling scope.
Um, no. I wasn't talking about pointers at all.
C doesn't directly implement pass-by-reference, so it's emulated by
passing a pointer (the pointer itself is, of course, passed by value).
For example:
#include <stdio.h>
static void increment(int *ptr)
{
*ptr ++;
}
int main(void)
{
int i = 42;
increment(&i);
printf("i = %d\n", i);
return 0;
}
Since ptr itself is never modified, the style issue I discussed above
doesn't arise. There would be no advantage stylistic or otherwise, in
making a local copy of ptr within the increment() function.
The case I was talking about was something more like this:
#include <stdio.h>
static void count_to_ten(int n)
{
while (n <= 10) {
printf("%d\n", n);
n++;
}
}
int main(void)
{
count_to_ten(5);
return 0;
}
Here the count_to_ten() function modifies the value of its parameter
(which obviously can have no effect on the caller). Some might
consider it poor style to the parameter like this, since it's natural
to think of n as the value that was passed in. But there's nothing
*really* wrong with it; n is just a local variable, and it's perfectly
legal to modify it. But in a more complex function, you might want to
look at the *original* value of n that was passed in; modifying n
makes this impossible. The problem can be avoided by copying n to
another local variable, and leaving the parameter value alone.
Either approach is acceptable, but some people are a bit uneasy about
modifying parameters.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Keith Thompson wrote: Dieter <us**********@comcast.net> writes:
Keith Thompson wrote: [...]
A parameter is effectively a local variable, initialized to the value given in the call. Taking its address is no more problematic that taking the address of any other local variable. The fact that it may have been passed in a register is irrelevant; if you take and use its address, the compiler *must* store it in memory somewhere. I tend to agree with you about the style issue of not modifying the value of a parameter within a function. If I see a reference to a parameter within a function, I tend to assume that it refers to the value that was passed by the caller; if the function modifies it, understanding the function requires a more complex mental model. But this is at least partly because I've spent a lot of time working in a language that makes parameters constant by default; I think that was a good idea from a language design point of view, but it's not what C does. In C, as I said, a parameter is really just a local variable, and as a *reader* of C you have to be prepared to deal with code that treats it as a variable.
Hi Kieth, thank you for your comments.
It's "Keith".
Oops, sorry about that, my fingers are accustomed to "ie" /Dieter/ So if I understand correctly, It's advisable, that when passing a pointer in the paramater of a called function (that needs to be modified for the originating (calling) scope, /for example/ ), that the paramater (passed pointer) should then be pointed to by a local pointer variable in the called function. This then makes *clear* the individuality between the original value being passed and the modification of that value, and is then,in effect, modifying the value in the calling scope.
Um, no. I wasn't talking about pointers at all.
C doesn't directly implement pass-by-reference, so it's emulated by passing a pointer (the pointer itself is, of course, passed by value).
For example:
#include <stdio.h>
static void increment(int *ptr) { *ptr ++; }
int main(void) { int i = 42; increment(&i); printf("i = %d\n", i); return 0; }
Since ptr itself is never modified, the style issue I discussed above doesn't arise. There would be no advantage stylistic or otherwise, in making a local copy of ptr within the increment() function.
The case I was talking about was something more like this:
#include <stdio.h>
static void count_to_ten(int n) { while (n <= 10) { printf("%d\n", n); n++; } }
int main(void) { count_to_ten(5); return 0; }
Here the count_to_ten() function modifies the value of its parameter (which obviously can have no effect on the caller). Some might consider it poor style to the parameter like this, since it's natural to think of n as the value that was passed in. But there's nothing *really* wrong with it; n is just a local variable, and it's perfectly legal to modify it. But in a more complex function, you might want to look at the *original* value of n that was passed in; modifying n makes this impossible. The problem can be avoided by copying n to another local variable, and leaving the parameter value alone.
Either approach is acceptable, but some people are a bit uneasy about modifying parameters.
I thank you sincerely and yes that makes perfect sense. :)
Dieter
In article <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.org> wrote: C doesn't directly implement pass-by-reference, so it's emulated by passing a pointer (the pointer itself is, of course, passed by value).
For example:
#include <stdio.h>
static void increment(int *ptr) { *ptr ++; }
Your example is somewhat marred by missing parentheses, or a
misplaced operator -- you mean:
++*ptr;
or
(*ptr)++;
[snippage]The case I was talking about was something more like this:
#include <stdio.h>
static void count_to_ten(int n) { while (n <= 10) { printf("%d\n", n); n++; } }
[snippage]Here the count_to_ten() function modifies the value of its parameter (which obviously can have no effect on the caller). Some might consider it poor style to the parameter like this, since it's natural to think of n as the value that was passed in.
I think this is fine, myself; but it is true that some prefer to
write:
static void count_to_ten(const int n0) {
int n = n0;
while (n <= 10) ...
}
Some (but not all) of these folks use the "const" qualifier, as shown
above, to make sure they do not accidentally modify n0.
I will take this opportunity to note that, in functions that do
deliberately modify a parameter, I tend to declare a local that is
one level "less pointer-y". For instance, in the code at the
start of this thread, I might write the routine that calls
scandir() as:
int somefunc(const char *dir, struct dirent ***anamelist) {
struct dirent **namelist;
int i, n;
n = scandir(dir, &namelist, NULL, NULL);
if (n == -1) ... handle error ...
for (i = 0; i < n; i++)
... work with namelist[i] ...
...
*anamelist = namelist; /* set extra return value */
return n; /* and return "main" return value */
}
This avoids the need to write (*anamelist) everywhere that "namelist"
appears. Of course &(*anamelist) simplifies to anamelist, so the
scandir call itself is no simpler; but the contents of the "for"
loop -- where we work with namelist[i]->field instead of
(*anamelist)[i]->field -- are much easier to read.
There is no particular reason to defer updating *anamelist until
the end of the function, but no particular reason to do it earlier,
either.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Chris Torek <no****@torek.net> writes: In article <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> wrote:C doesn't directly implement pass-by-reference, so it's emulated by passing a pointer (the pointer itself is, of course, passed by value).
For example:
#include <stdio.h>
static void increment(int *ptr) { *ptr ++; }
Your example is somewhat marred by missing parentheses, or a misplaced operator -- you mean:
++*ptr;
or
(*ptr)++;
D'oh! Thanks for catching that. (I did compile and run it; I just
missed the fact that the output was "i = 42" rather than the intended
"i = 43".)
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
On Fri, 06 Jan 2006 18:46:21 +0000, Jordan Abel wrote: On 2006-01-06, Jack Klein <ja*******@spamcop.net> wrote:
[...] int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
[snip] On the last line of code above, you pass a pointer to 'namelist' (therefore a char ***) to scandir(). Presumably this function checks whether the pointed-to char ** is NULL or not, and if it is NULL, it allocates the necessary memory. And also presumably, if the pointed-to char ** is not NULL, it assumes that it points to valid memory and uses it.
My understanding of the manpage on my implementation, backed up by my reading of the source on my particular implementation, is that it ignores any previously-pointed-to value and only stores to *namelist.
If that's true for the OP's platform too (which seems likely) then the
behaviour Jack guessed scandir() to have wasn't a contributor to the
problem. When you write *namelist above, I assume that you refer to the
parameter within scandir() - with type struct dirent ***, not the variable
passed by the caller as &namelist, with type struct dirent **.
[why are you calling 'struct dirent' 'char'?]
At the end you try to free a pointer that was not allocated.
You snipped this part, so I can't comment on it. According to the manpage, you are supposed to free each member of *namelist [individual struct dirent *] in turn, then free *namelist. The question is, what differs between his two versions?
The answer that's turned up elsewhere in the thread is:
since namelist is being passed to getFileNames() as a struct dirent **,
the operations performed on it by scandir() are lost to the caller - it
needs to be passed as &namelist with getFileNames() taking a struct
dirent ***, in the same way that scandir() does.
The file-scope declaration set namelist to NULL, so that the user-defined
function to free it returned without problems, but when defined at
function scope in main(), given that it was (a) not initialised and (b)
the intended changes to the initial value were lost due to "passing by
value rather than reference", the user-defined function to free it was
operating on an invalid pointer. I've re-copied part of that function
below:
int freeFileNames(struct dirent **namelist, int entries)
{
int i;
if (namelist == NULL)
return 0;
else{
....
free(namelist[i]);
....
free(namelist);
Both lines above invoke UB when namelist is defined at function-scope
in main since by this point it still hasn't been set.
namelist = NULL;
Redundant assignment since the function is operating on a different copy
of the pointer than the caller and is about to return anyhow.
}
return 1;
}
-- http://members.dodo.com.au/~netocrat
Dieter wrote: int getFileNames(char *directory, struct dirent **namelist) { int n, i;
n = scandir(directory, &namelist, 0, alphasort);
Hi,
As other groups members has remarked, the problem was in the call to
scandir (the program doesn't works if the variable is global and also
doesn't works if it is local. The only diference is how bad are the
effects).
I want only to remark two things about modify a function parameter:
a) The changes done to the value of a parameter will be always lost at
function return.
b) Change a parameter is under stylistic discussion (in particular, I
never do it. If necessary, I declare a local and init it with the
parameter value), and, who knows if allowed by standard. By example, a
SPARC CPU uses registers to pass parameters, so, the address of a
parameter is something that breaks to normal function prologs
(assembler code at start of fucntion).
In conclusion, any line of the kind "¶meter" must be carefully
reviewed.
Kind regards.
Richard Heathfield wrote: M.B said:
its a pass by value v/s pass by reference issue Since C doesn't have pass by reference, it is clear to me that you are talking nonsense.
I presume u area c++ guy to talk like this.
pass by reference is a generic term for ur info.
C iimplements this by pointers.
- M.B -- Richard Heathfield "Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk email: rjh at above domain (but drop the www, obviously)
Chuck F. wrote: M.B wrote: sorry if thjis is a duplicate reply...
I guess this is a scope issue for variable "namelist" I suggest to change the function int getFileName(char *,struct dirent ***); and make necessary changes to code. it may work fine
bcoz scandir i guess sets "struct dirent **" itself. if its global all is fine, but local variables 0 its problem-same as pass by value Please use English, not dudespeak, in this newsgroup, and include adequate context. Between the two your article is totally meaningless. See below for further advice.
For letting out context, my mistake sorry.
English - hope this is not an english literature group. People want
answers and its enough if they get those in anyway. go hell with
correct English.
Also please check if the advice given in your signature works
correctly.
And finally, noone has time and patience to reply to trolls.
-- "If you want to post a followup via groups.google.com, don't use the broken "Reply" link at the bottom of the article. Click on "show options" at the top of the article, then click on the "Reply" at the bottom of the article headers." - Keith Thompson More details at: <http://cfaj.freeshell.org/google/>
Randy Howard wrote: M.B wrote (in article <11*********************@z14g2000cwz.googlegroups. com>):
All of which points out why we want queries to be topical. Once you involve an unknown header (dirent) and an unknown function (scandir) nobody can have any accurate idea what goes on. This is why this whole thread should have been on a newsgroup dealing with your system in the first place. btw dirent or dirent.h is not alien. its of course not in ansi but in posix (k&r also mentions it)
It most certainly is alien to those not using a POSIX platform, and IIRC, it pre-dates POSIX. Even so, there is no guarantee that a standard conforming C compiler and linker will no a thing about it. That's the whole point.
The fact that Jack could make an educated guess does not affect this. His guess could well have been total nonsense, and could have missed important factors. There is (in principle) noone here to correct any mistakes.
I agree here. Anyone replying here want to help in any case. But we all can help in giving suggestions but not spoonfeed. I may not know what others know . knowlegde sharing is the idea here.
No, the issue raised was that if someone asks a question about a nonstandard extension that is rarely seen, or at least not by the regulars, then any responses offered could be complete bullschildt, yet go undetected. When you ask a question in a forum populated by people that specialize on the topic, you get much better (and peer reviewed) answers. When you ask a question on GPS navigation in comp.graphics.apps.photoshop, no telling what will happen.
I agree to some extend, but the question is whether we can push off any
queries just because they stray slightly in to an area beyond the group
topic (is this a sacred line ?).
in any case the problem here was not due to use of any non standard
functions etc (just that it was part of the code).
-- Randy Howard (2reply remove FOOBAR) "The power of accurate observation is called cynicism by those who have not got it." - George Bernard Shaw How 'bout them Horns?
"M.B" <mb*******@gmail.com> writes: Chuck F. wrote: M.B wrote: > sorry if thjis is a duplicate reply... > > I guess this is a scope issue for variable "namelist" I suggest > to change the function int getFileName(char *,struct dirent > ***); and make necessary changes to code. it may work fine > > bcoz scandir i guess sets "struct dirent **" itself. if its > global all is fine, but local variables 0 its problem-same as > pass by value Please use English, not dudespeak, in this newsgroup, and include adequate context. Between the two your article is totally meaningless. See below for further advice.
For letting out context, my mistake sorry. English - hope this is not an english literature group. People want answers and its enough if they get those in anyway. go hell with correct English.
You don't need to write flawless English, especially if it doesn't
happen to be your native language, but avoiding abbreviations like "u"
for "you" and "bcoz" for "because" make it *much* easier to understand
you.
Also please check if the advice given in your signature works correctly.
As far as I know it does. Are you saying it doesn't?
And finally, noone has time and patience to reply to trolls.
Chuck F. is not a troll. Trust me on this.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
M.B said: Richard Heathfield wrote: M.B said:
> its a pass by value v/s pass by reference issue Since C doesn't have pass by reference, it is clear to me that you are talking nonsense.
I presume u area c++ guy to talk like this.
I don't know the u area. I'm from the UK. As for C++, no, I'm not talking
about C++.
pass by reference is a generic term for ur info.
I've never been to ur. I repeat that C does not have pass by reference. If
you disagree, show me the part of the C Standard that supports your
viewpoint.
C iimplements this by pointers.
In C, pointers are passed by value.
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
M.B wrote: Richard Heathfield wrote:
M.B said:
its a pass by value v/s pass by reference issue
Since C doesn't have pass by reference, it is clear to me that you are talking nonsense.
I presume u area c++ guy to talk like this. pass by reference is a generic term for ur info. C iimplements this by pointers.
M.B., you clearly don't know what 'pass by reference' means. C doesn't
do it, even with pointers. Whether C++ does it is of no interest here.
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
On 2006-01-07, Joe Wright <jo********@comcast.net> wrote: M.B wrote: Richard Heathfield wrote:
M.B said:
its a pass by value v/s pass by reference issue
Since C doesn't have pass by reference, it is clear to me that you are talking nonsense.
I presume u area c++ guy to talk like this. pass by reference is a generic term for ur info. C iimplements this by pointers.
M.B., you clearly don't know what 'pass by reference' means. C doesn't do it, even with pointers. Whether C++ does it is of no interest here.
Yes it does. time() takes its argument by reference [as do many other
functions in time.h, for historical reasons] You are conflating a
generic concept with a specific feature C++ has that C does not.
Joe Wright wrote: M.B wrote:
Richard Heathfield wrote:
M.B said:
its a pass by value v/s pass by reference issue
Since C doesn't have pass by reference, it is clear to me that you are talking nonsense.
I presume u area c++ guy to talk like this. pass by reference is a generic term for ur info. C iimplements this by pointers.
M.B., you clearly don't know what 'pass by reference' means. C doesn't do it, even with pointers. Whether C++ does it is of no interest here.
Ah, newbies!
Definition of 'pass by reference' http://publib.boulder.ibm.com/infoce...ef/cplr233.htm
Richard Heathfield <in*****@invalid.invalid> writes: M.B said:
[...] I've never been to ur. I repeat that C does not have pass by reference. If you disagree, show me the part of the C Standard that supports your viewpoint.
C iimplements this by pointers.
In C, pointers are passed by value.
I think M.B has a point, though he didn't state it particularly
coherently.
No, the C doesn't directly support pass by reference, but, like many
other things, it does support it indirectly.
C doesn't support linked lists or binary trees, but they can easily be
implemented in C.
We all know what the relevant features of the C language are and how
they can be used to implement what other languages might implement
more directly. The only argument here is about the meaning of the
statement "C has pass-by-value" or "C supports pass-by-value"; this
debate would perhaps be more appropriate in an English usage
newsgroup.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Keith Thompson wrote: Richard Heathfield <in*****@invalid.invalid> writes:
M.B said: [...]
I've never been to ur. I repeat that C does not have pass by reference. If you disagree, show me the part of the C Standard that supports your viewpoint.
C iimplements this by pointers.
In C, pointers are passed by value.
I think M.B has a point, though he didn't state it particularly coherently.
No, the C doesn't directly support pass by reference, but, like many other things, it does support it indirectly.
In the context of passing a variable 'by reference' so that original 'object'
can be altered, c does indeed "pass by reference." In the context of passing
an immutable variable(object) so that the original 'object' remains unaltered
has morphed "pass by reference" from it's original definition since the
creation of the concept "pass by reference" pioneered by early language
developers.
C doesn't support linked lists or binary trees, but they can easily be implemented in C.
The manor of how a data construct is passed to sub functions(methods) has no
relation to the data construct itself, i.e. a linked list, tree of any flavor,
or even "arrays". Any data container exceeding the ability of the cpu to
"store" the value in one of its processing registers is an artifact and the
cpu has no "intelligence" to directly use it.
A cpu "knows" how to add to primitive ints, but has not knowledge how to
concatenate two human readable "strings."
We all know what the relevant features of the C language are and how they can be used to implement what other languages might implement more directly. The only argument here is about the meaning of the statement "C has pass-by-value" or "C supports pass-by-value"; this debate would perhaps be more appropriate in an English usage newsgroup.
Keith Thompson said: Richard Heathfield <in*****@invalid.invalid> writes: M.B said: [...] I've never been to ur. I repeat that C does not have pass by reference. If you disagree, show me the part of the C Standard that supports your viewpoint.
C iimplements this by pointers.
In C, pointers are passed by value.
I think M.B has a point,
I don't.
though he didn't state it particularly coherently.
Quite.
No, the C doesn't directly support pass by reference, but, like many other things, it does support it indirectly.
I don't see that at all. All function argument expressions are evaluated and
those resulting *values* are given to the function concerned. A clearer
case of pass-by-value you could not hope to see.
The reason I think it matters is this: once a newcomer to C works out that
*everything* in C is pass-by-value, it makes the abstract machine much
easier to understand, much more obvious. There is a didactic value in
insisting on what is, after all, only the truth.
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999 http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Joseph Dionne <jd*****@hotmail.com> writes: Keith Thompson wrote: Richard Heathfield <in*****@invalid.invalid> writes:
M.B said: [...]
I've never been to ur. I repeat that C does not have pass by reference. If you disagree, show me the part of the C Standard that supports your viewpoint.
C iimplements this by pointers.
In C, pointers are passed by value. I think M.B has a point, though he didn't state it particularly coherently. No, the C doesn't directly support pass by reference, but, like many other things, it does support it indirectly.
In the context of passing a variable 'by reference' so that original 'object' can be altered, c does indeed "pass by reference." In the context of passing an immutable variable(object) so that the original 'object' remains unaltered has morphed "pass by reference" from it's original definition since the creation of the concept "pass by reference" pioneered by early language developers.
[...]
Sorry, but I don't understand what you mean. Are you disagreeing with
my statement that C doesn't support pass by reference indirectly, but
does support it indirectly?
We all know about emulating pass by reference using pointers. If
you're talking about something else, can you provide an example?
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: mike420 |
last post by:
I think everyone who used Python will agree that its syntax is
the best thing going for it. It is very readable and easy
for everyone to learn. But, Python does not a have very good
macro...
|
by: Minti |
last post by:
I was reading some text and I came across the following snippet
switch('5')
{
int x = 123;
case '5':
printf("The value of x %d\n", x);
break;
}
|
by: Code Raptor |
last post by:
Folks,
I am hitting a segfault while free()ing allocated memory - to make it
short, I have a linked list, which I try to free node-by-node. While
free()ing the 28th node (of total 40), I hit a...
|
by: G Patel |
last post by:
I've seen some code with extern modifiers in front of variables
declared inside blocks. Are these purely definitions (no definition)
or are they definitions with static duration but external...
|
by: seamoon |
last post by:
Hi,
I'm doing a simple compiler with C as a target language. My language uses
the possibility to declare variables anywhere in a block with scope to the
end of the block. As I remembered it this...
|
by: BT |
last post by:
Ok, for a school assignment we have to use a pointer for an array of
ints, intstead of the usual X way, it compiles fine but when i run
it I am getting a seg fault that i can't figure out how to...
|
by: nobrow |
last post by:
Okay ... Im out of practice. Is it not possible to have a 2D array
where each column is of a different type, say an int and a struct*? The
following seg faults for me and I cant figure out what I...
|
by: Neal Becker |
last post by:
One thing I sometimes miss, which is common in some other languages (c++),
is idea of block scope. It would be useful to have variables that did not
outlive their block, primarily to avoid name...
|
by: somebody |
last post by:
There are two files below named search.c and search.h.
In the for loop in search.c, the for loop never exits,
even if mystruct.field1 has no match. Instead of
exiting the for loop it keeps going...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
| | |