473,395 Members | 2,446 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

segfault w/ block, but not file scope

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
Jan 6 '06 #1
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;
}
Jan 6 '06 #2
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
Jan 6 '06 #3
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
Jan 6 '06 #4
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/>
Jan 6 '06 #5
M.B
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

Jan 6 '06 #6
M.B
please check
pass by value
v/s pass by ref/pointers carefully
hope this helps to solve the issue

Jan 6 '06 #7
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.
Jan 6 '06 #8
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
Jan 6 '06 #9
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.
Jan 6 '06 #10
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
Jan 6 '06 #11
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
Jan 6 '06 #12
M.B

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

Jan 6 '06 #13
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

Jan 6 '06 #14
M.B
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;
}

Jan 6 '06 #15
M.B

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/>


Jan 6 '06 #16
M.B

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/>


Jan 6 '06 #17
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. :)
Jan 6 '06 #18
"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.
Jan 6 '06 #19
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 "&parameter" must be carefully
reviewed.

Kind regards.

Jan 6 '06 #20
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)
Jan 6 '06 #21
M.B

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

Jan 6 '06 #22
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 "&parameter" must be carefully
reviewed.

Kind regards.

Jan 6 '06 #23
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/>
Jan 6 '06 #24
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 "&parameter" 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.

Jan 6 '06 #25
M.B

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 "&parameter" 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.


Jan 6 '06 #26
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?

Jan 6 '06 #27
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.

Jan 6 '06 #28
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
Jan 6 '06 #29
"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.
Jan 6 '06 #30
"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 "&parameter" 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.
Jan 6 '06 #31
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 "&parameter" 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
Jan 6 '06 #32
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.
Jan 7 '06 #33
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
Jan 7 '06 #34
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.
Jan 7 '06 #35
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.
Jan 7 '06 #36
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
Jan 7 '06 #37
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 "&parameter" must be carefully
reviewed.

Kind regards.

Jan 7 '06 #38
M.B
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)


Jan 7 '06 #39
M.B

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/>


Jan 7 '06 #40
M.B

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?


Jan 7 '06 #41
"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.
Jan 7 '06 #42
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)
Jan 7 '06 #43
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 ---
Jan 7 '06 #44
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.
Jan 7 '06 #45
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
Jan 7 '06 #46
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.
Jan 7 '06 #47
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.

Jan 7 '06 #48
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)
Jan 7 '06 #49
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.
Jan 7 '06 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

699
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...
18
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; }
6
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...
12
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...
7
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...
7
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...
8
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...
24
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...
10
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
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...
0
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
0
BarryA
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...
1
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...
0
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...
0
marktang
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,...
0
jinu1996
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...
0
tracyyun
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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.