On November 19, 2009 18:53, in comp.lang.c, frank
Function bar accepts a pointer to a pointer-to-char, right?
Here, you take that pointer to a pointer-to char, find what it points
to, and change that value so that it now points to the data area you
have malloc()ed.
In other words,
Before the line,
s pointed to a pointer, and that pointer pointed somewher
After the line,
s still pointed to the same place, but the contents of that place have
been changed to now contain the value returned by malloc()
With me so far?
yup.
Here, you allocate a as a pointer to pointer-to-char. But, you leave it
uninitialized; a doesn't point at anything in particular (it's value is
indeterminate).
Now, you pass a, an unitialized pointer to bar(). Remember what bar()
will do; it will try to modify the area that this pointer points to.
But, this pointer has an indeterminate value; it /could/ point anywhere,
including outside of the space in which your program and it's data
reside.
<off_topic>
Now, when a Unix process (that being the platform you are apparently
compiling and running on) tries to access memory outside of the bounds
of the process's memory map, Unix protects that memory, and sends a
SIGSEGV signal to the process. Uncaught, this SIGSEGV will cause the
process to abort, with a "Segmentation Violation" error message. That's
what you got. </off_topic>
The cure for your problem is to, prior to invoking function bar(),
*initialize* the pointer so that it points at a pointer-to-char.
Given your existing code, what you really wanted to do was...
a = &b;
bar ( a );
or, in shorter form
bar (&b);
Alright, thx Lew. When I try to work with indirection and do it from
scratch, I think I might resemble a beautiful animal like a caribou: 15
minutes after it's born, covered with afterbirth, wobbly on it's too-long
limbs.
So when you have a constructor that uses char **, what you want to do is
declare a pointer to char and then pass it preceded by the reference
operator, & .
I figured I would have this correct if I could print out the vlaues that
malloc returned. Indeed, it's plum necessary for robust code to at least
check for a positive value.
I've got the parts here, dan@dan-desktop:~/source$ gcc -std=c99 -Wall -
Wextra malloc1.c -o out
malloc1.c: In function ‘bar’:
malloc1.c:8: warning: initialization makes integer from pointer without a
castdan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra malloc1.c -o out
malloc1.c: In function ‘bar’:
malloc1.c:8: warning: initialization makes integer from pointer without a
cast
malloc1.c:9: warning: format ‘%d’ expects type ‘int’, but argument 2 has
type ‘char **’
malloc1.c:8: warning: unused variable ‘r’
malloc1.c: In function ‘main’:
malloc1.c:26: warning: unused variable ‘r’
dan@dan-desktop:~/source$ ./out
-1081554784
qwerty
0
dan@dan-desktop:~/source$ cat malloc1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void bar( char **s )
{
*s = malloc( 10 );
int r = &s;
printf("%d\n", s);
}
char *baz( void )
{
char *s = malloc( 10 );
return s;
}
int
main(void)
{
void bar ( char ** );
char * baz ( void );
char * b;
int c, r;
bar ( &b );
b = baz( );
#if 1
c = * b;
strcpy(b, "qwerty");
printf ("%s\n", b);
printf ("%d\n", c);
#endif
return 0;
}
// gcc -std=c99 -Wall -Wextra malloc1.c -o out
dan@dan-desktop:~/source$
malloc1.c:9: warning: format ‘%d’ expects type ‘int’, but argument 2 has
type ‘char **’
malloc1.c:8: warning: unused variable ‘r’
malloc1.c: In function ‘main’:
malloc1.c:26: warning: unused variable ‘r’
dan@dan-desktop:~/source$ ./out
-1081554784
qwerty
0
dan@dan-desktop:~/source$ cat malloc1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void bar( char **s )
{
*s = malloc( 10 );
int r = &s;
printf("%d\n", s);
}
char *baz( void )
{
char *s = malloc( 10 );
return s;
}
int
main(void)
{
void bar ( char ** );
char * baz ( void );
char * b;
int c, r;
bar ( &b );
b = baz( );
#if 1
c = * b;
strcpy(b, "qwerty");
printf ("%s\n", b);
printf ("%d\n", c);
#endif
return 0;
}
// gcc -std=c99 -Wall -Wextra malloc1.c -o out
dan@dan-desktop:~/source$
but I seem to be unable to dereference:
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra malloc1.c -o out
malloc1.c: In function ‘bar’:
malloc1.c:8: warning: initialization makes integer from pointer without a
cast
malloc1.c:9: warning: format ‘%d’ expects type ‘int’, but argument 2 has
type ‘char **’
malloc1.c:8: warning: unused variable ‘r’
malloc1.c: In function ‘main’:
malloc1.c:26: warning: unused variable ‘r’
dan@dan-desktop:~/source$ ./out
-1081554784
qwerty
0
dan@dan-desktop:~/source$ cat malloc1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void bar( char **s )
{
*s = malloc( 10 );
int r = &s;
printf("%d\n", s);
}
char *baz( void )
{
char *s = malloc( 10 );
return s;
}
int
main(void)
{
void bar ( char ** );
char * baz ( void );
char * b;
int c, r;
bar ( &b );
b = baz( );
#if 1
c = * b;
strcpy(b, "qwerty");
printf ("%s\n", b);
printf ("%d\n", c);
#endif
return 0;
}
// gcc -std=c99 -Wall -Wextra malloc1.c -o out
dan@dan-desktop:~/source$
Any takers on this one? One problem with programs that have over fifty
options is that you can't find the one option that any indent program
really needs, i.e., the tab length.