segfault w/ block, but not file scope

N

Netocrat

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);
....
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;
}
 
K

Keith Thompson

M.B said:
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.
 
R

Richard Heathfield

M.B said:
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.
 
J

Joe Wright

M.B said:
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.
 
J

Jordan Abel

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.
 
K

Keith Thompson

Richard Heathfield said:
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.
 
J

Joseph Dionne

Keith said:
Richard Heathfield said:
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."
 
R

Richard Heathfield

Keith Thompson said:
Richard Heathfield said:
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.
 
K

Keith Thompson

Joseph Dionne said:
Keith said:
Richard Heathfield said:
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?
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said:
Richard Heathfield said:
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.

Yes, it's important to understand that all function arguments in C are
passed by value. C doesn't have pass-by-reference as a language
feature. But it does support pass-by-reference as a programming
technique.

Suppose I have some Pascal code that uses pass-by-reference (no
guarantee that I've gotten the syntax correct):

function increment(var n: integer)
begin
n := n + 1;
end;

...

n : integer;
n := 42;
increment(n);

The translation to C is straightforward:

void increment(int *n)
{
(*n)++;
}

...

int n;
n = 42;
increment(&n);

Of course you're passing the address of n *by value* to the
increment() function. C doesn't directly support pass-by-reference.
But passing a pointer argument is how you, as a programmer, can
*implement* pass-by-reference.

(I'm 100% certain that I'm not telling you anything you don't already
know; the point is to figure out just where we disagree.)

Perhaps it would be clearer to use different names for the language
feature and the programming technique. I don't have any good ideas
about that. Since it's such a common technique, it should have a
pithier name than "passing the address of a variable so the function
can use it to modify the value of the variable itself".
 
J

Joseph Dionne

Keith said:
Joseph Dionne said:
Keith said:
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?

I disagree with your assertion that c does not support pass by reference. I
am saying 'pass by reference' meant passing an address to variable memory in a
pointer, which by the way *is* a construct the cpu *knows* how to handle.

"pass by reference', since the creation of c++ and other OOP languages, has
been a new "meaning".
 
J

Joseph Dionne

Keith said:
Richard Heathfield said:
Keith Thompson said:
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.


Yes, it's important to understand that all function arguments in C are
passed by value. C doesn't have pass-by-reference as a language
feature. But it does support pass-by-reference as a programming
technique.

Suppose I have some Pascal code that uses pass-by-reference (no
guarantee that I've gotten the syntax correct):

function increment(var n: integer)
begin
n := n + 1;
end;

...

n : integer;
n := 42;
increment(n);

The translation to C is straightforward:

void increment(int *n)
{
(*n)++;
}

...

int n;
n = 42;
increment(&n);

Of course you're passing the address of n *by value* to the
increment() function. C doesn't directly support pass-by-reference.
But passing a pointer argument is how you, as a programmer, can
*implement* pass-by-reference.

(I'm 100% certain that I'm not telling you anything you don't already
know; the point is to figure out just where we disagree.)

Perhaps it would be clearer to use different names for the language
feature and the programming technique. I don't have any good ideas
about that. Since it's such a common technique, it should have a
pithier name than "passing the address of a variable so the function
can use it to modify the value of the variable itself".

It has been twenty years since I coded pascal, I will dispute your pascal code
other than to ask is "increment(1)" syntactically correct and will the pascal
increment() increment memory address 0x0001?


But, the link below gives a good, concrete explanation of "pass by reference"
and "pass by value".

http://csis.pace.edu/~bergin/iticse2000/params.html

In your c code, increment(&n) *is* pass by reference simply because the
original memory can be altered, but I can code an increment() function for
pass by value too.

int increment(int ii) { return(ii+1); }

The original value of ii will remain unaltered, unless of course you code
ii = increment(ii);
 
R

Richard Heathfield

Keith Thompson said:
(I'm 100% certain that I'm not telling you anything you don't already
know; the point is to figure out just where we disagree.)

I'm for whatever makes C easier to understand. Heaven knows it's hard enough
already, without making it harder.

When you say "pointers" and "pass by reference", yes, OF COURSE I know what
you mean. But J Random Newbie over there, who already has a hundred new
concepts buzzing around his head right now and who does not fully
understand what pointers *are* yet, let alone what they are *for*, is going
to think "pointers, right, the little * thing, okay, pass-by-reference,
right, * means pass by reference, which means I can update it, great..."
and he is going to think he understands things a little better - and then
he is (eventually) going to wonder why this:

void allocstr(char *s, size_t n)
{
s = malloc(n);

if(s == NULL) abort();
}

doesn't seem to do what he wants.
 
J

Joseph Dionne

Richard said:
Keith Thompson said:




I'm for whatever makes C easier to understand. Heaven knows it's hard enough
already, without making it harder.

When you say "pointers" and "pass by reference", yes, OF COURSE I know what
you mean. But J Random Newbie over there, who already has a hundred new
concepts buzzing around his head right now and who does not fully
understand what pointers *are* yet, let alone what they are *for*, is going
to think "pointers, right, the little * thing, okay, pass-by-reference,
right, * means pass by reference, which means I can update it, great..."
and he is going to think he understands things a little better - and then
he is (eventually) going to wonder why this:

void allocstr(char *s, size_t n)
{
s = malloc(n);

if(s == NULL) abort();
}

doesn't seem to do what he wants.

A pointer can be passed by value, it that address of the memory storing an
address to memory used for "data", or passed by reference to "hide" it memory
address from the function called.

For example, using your allocstr() function called by value;

{
char *t;

allocstr(t,10);
}

Will not have the desired result, char pointer t will remain pointing at it
original ram address both before and after the call to allocstr(). However, I
can pass a reference to t, syntactically &s, that WILL have the desired result.

Further "by value" passing of pointers is strlen() implementation, for example;

int strlen(char *s)
{
int ii;

for(ii=0;*s;ii++);

return(ii);
}

{
char *t = "hello world";

strlen(t);
}

The t variable still points at 'h' because the contents of t is passed by
value, Pointers are primitives in c, just like char, int, and long.
 
J

Joseph Dionne

Richard said:
Keith Thompson said:




I'm for whatever makes C easier to understand. Heaven knows it's hard enough
already, without making it harder.

When you say "pointers" and "pass by reference", yes, OF COURSE I know what
you mean. But J Random Newbie over there, who already has a hundred new
concepts buzzing around his head right now and who does not fully
understand what pointers *are* yet, let alone what they are *for*, is going
to think "pointers, right, the little * thing, okay, pass-by-reference,
right, * means pass by reference, which means I can update it, great..."
and he is going to think he understands things a little better - and then
he is (eventually) going to wonder why this:

void allocstr(char *s, size_t n)
{
s = malloc(n);

if(s == NULL) abort();
}

doesn't seem to do what he wants.

(Corrected. I'll reread what I type from now on.)

A pointer can be passed by value -- its contents,the address of the memory use
for "data" storage, to "hide" its address from the function called, or the
address location of the pointer itself can be passed by reference to "expose"
its "data content" to modification.

For example, using your allocstr() function called by value;

{
char *t;

allocstr(t,10);
}

Will not have the desired result, char pointer t will remain pointing at it
original ram address both before and after the call to allocstr(). However, I
can pass a reference to t, syntactically &t, that WILL have the desired result.

Further "by value" passing of pointers is strlen() implementation, for example;

int strlen(char *s)
{
int ii;

for(ii=0;*s;ii++);

return(ii);
}

{
char *t = "hello world";

strlen(t);
}

The t variable still points at 'h' because the contents of t is passed by
value, Pointers are primitives in c, just like char, int, and long.

Are we *debating* language syntax or capabilities?
 
K

Keith Thompson

Joseph Dionne said:
Keith Thompson wrote: [...]
Suppose I have some Pascal code that uses pass-by-reference (no
guarantee that I've gotten the syntax correct):
function increment(var n: integer)
begin
n := n + 1;
end;
...
n : integer;
n := 42;
increment(n);
The translation to C is straightforward:
void increment(int *n)
{
(*n)++;
}

...

int n;
n = 42;
increment(&n);
It has been twenty years since I coded pascal, I will dispute your
pascal code other than to ask is "increment(1)" syntactically correct
and will the pascal increment() increment memory address 0x0001?

<OT>
No, that's not a problem. In Pascal, for an ordinary (pass-by-value)
parameter, the argument can be any expression of the appropriate type.
For a var (pass-by-reference) parameter, the actual parameter must
be a variable.
In your c code, increment(&n) *is* pass by reference simply because
the original memory can be altered, but I can code an increment()
function for pass by value too.

The call increment(&n) passes the *value* of &n. This is used to
implement the equivalent of passing n by reference, something that the
C language doesn't directly support.
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said:

I'm for whatever makes C easier to understand. Heaven knows it's hard enough
already, without making it harder.

When you say "pointers" and "pass by reference", yes, OF COURSE I know what
you mean. But J Random Newbie over there, who already has a hundred new
concepts buzzing around his head right now and who does not fully
understand what pointers *are* yet, let alone what they are *for*, is going
to think "pointers, right, the little * thing, okay, pass-by-reference,
right, * means pass by reference, which means I can update it, great..."
and he is going to think he understands things a little better - and then
he is (eventually) going to wonder why this:

void allocstr(char *s, size_t n)
{
s = malloc(n);

if(s == NULL) abort();
}

doesn't seem to do what he wants.

Then we need to make it very clear to J Random Newbie that C doesn't
support pass by reference as a languag construct. Don't say that the
"*" means pass by reference; say that the "*" means you're passing a
pointer value, which can be used to do the equivalent of pass by
reference. Until J Random Newbie is able to hold that entire complex
thought in his head, he's not going to be able to be an effective C
programmer.

Pass by reference is a very common and useful programming technique,
one that C supports quite well (though arguably a little more clumsily
than some other languages do).
 
J

Joe Wright

Jordan said:
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.

I may have to look this up because an exact example eludes me right now.
In general, 'pass by reference' means that the argument the callee
receives is the object itself, not a pointer to it. Vague memory has it
that dBASE IV would pass by reference like..

MANY = 0

INCREMENT(MANY)

...would result in MANY being equal 1 because it was MANY, not its value
which is passed to INCREMENT().

PROCEDURE INCREMENT(N)
N = N + 1
RETURN
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top