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

Pointer confusion with passing string array -- Segmentation fault

P: n/a
I'm trying to create a function that given a string, tokenize it and
put into a dynamically-sized array of char* which is in turn also
dynamically allocated based on the string token length.

I call the function using this code fragement in my main function:
---
char** arg_array;
arg_count = create_arg_array(command, argument, arg_array);

for(count = 0; count < arg_count; count++)
printf("arg_array[%d]: %s\n", count, arg_array[count]);
---
And it always crashes with a segmentation fault when going into the
for loop to print out the array of strings. Why does it crash when
I've already called malloc and realloc (inside create_arg_array()
function) to reserve some memory for the string array?

The create_arg_array is given below.
What's wrong with this function?
---
size_t create_arg_array(char* file, char* arg, char** array){
size_t count;
char* argument;

count = 1;
/* 1 for the filename and 1 for the terminating NULL ptr. */
array = (char**) malloc(count * sizeof(char*));

array[0] = (char*) malloc(strlen(file) + 1);
strcpy((*array)[0], file);

if(arg != NULL){
argument = strtok(arg, " \n");
if(argument != NULL){
array = (char**) realloc(array, (count + 1) * sizeof(char*));
array[count] = (char*) malloc(strlen(argument) + 1);
strcpy(array[count], argument);
count++;
}
while((argument = strtok(NULL, " \n")) != NULL){
array = (char**) realloc(array, (count + 1) * sizeof(char*));
array[count] = (char*) malloc(strlen(argument) + 1);
strcpy(array[count], argument);
count++;
}
}
++count;
array = (char**) realloc(array, (count * sizeof(char*)));
array[count-1] = NULL;

return count-1; /* Minus 1 for the ending NULL */
}
---
I thought the address returned by realloc and malloc is lost when I
return to main function and I've also tried changing the function to
accept a pointer to the array of string (char***) but it doesn't help.

Any advice appreciated.
Thank you.

Goh, Yong Kwang
Singapore
go**********@hotmail.com
Nov 14 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On 2 Apr 2004 17:31:23 -0800, go**********@hotmail.com (Goh, Yong
Kwang) wrote in comp.lang.c:
I'm trying to create a function that given a string, tokenize it and
put into a dynamically-sized array of char* which is in turn also
dynamically allocated based on the string token length.

I call the function using this code fragement in my main function:
---
char** arg_array;
arg_count = create_arg_array(command, argument, arg_array);

for(count = 0; count < arg_count; count++)
printf("arg_array[%d]: %s\n", count, arg_array[count]);
---
And it always crashes with a segmentation fault when going into the
for loop to print out the array of strings. Why does it crash when
I've already called malloc and realloc (inside create_arg_array()
function) to reserve some memory for the string array?

The create_arg_array is given below.
What's wrong with this function?
The main answer to your primary question is covered in this
newsgroup's FAQ, specifically:

http://www.eskimo.com/~scs/C-faq/q4.8.html
---
size_t create_arg_array(char* file, char* arg, char** array){
size_t count;
char* argument;

count = 1;
/* 1 for the filename and 1 for the terminating NULL ptr. */
array = (char**) malloc(count * sizeof(char*));

array[0] = (char*) malloc(strlen(file) + 1);


Casting the pointer returned by malloc() is unnecessary in C and
considered bad form by most experienced C programmers. At best it is
useless, a redundant cast. At worst it silences an important compiler
diagnostic if you neglected to include <stdlib.h> to have a proper
prototype in scope.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
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
Nov 14 '05 #2

P: n/a


Goh, Yong Kwang wrote:
I'm trying to create a function that given a string, tokenize it and
put into a dynamically-sized array of char* which is in turn also
dynamically allocated based on the string token length.

..........snip...........
---
size_t create_arg_array(char* file, char* arg, char** array){
size_t count;
char* argument;
---
I thought the address returned by realloc and malloc is lost when I
return to main function and I've also tried changing the function to
accept a pointer to the array of string (char***) but it doesn't help.


A char *** parameter would be correct. But you need to correct
the logic errors. Another approach would be to define a
data type that will contain all the data that you need.

like:
typedef struct DATA
{
char *fdata /* contents of the entire file */
char **pdata /* An array of pointers to the file data */
size_t count /* A count of the array of pointers */
} DATA;

Then you can write functions to manipulate this datatype.

Ex.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FNAME "test.txt" /* File name goes here */

/*test.txt contents:

Bill:JOHN:HARRY:AL:WILLIAM:
FRANK:LARRY:RON

*/

typedef struct DATA
{
char *fstring;
char **pstring;
size_t count;
} DATA;

DATA getDATA(const char *fname, const char *delim);
void freeDATA(DATA *p);
void printDATA(DATA *p);

int main(void)
{
DATA data = getDATA(FNAME, ":\n");

printDATA(&data);
freeDATA(&data);
return 0;
}

DATA getDATA(const char *fname, const char *delim)
{
FILE *fp;
DATA p = {NULL};
char *tmp, buf[64], **tmpp;
size_t sz;

if((fp = fopen(fname,"r")) == NULL) return p;
for(sz = 0 ; (fgets(buf,sizeof buf, fp)); )
{
tmp = realloc(p.fstring, (sz += strlen(buf))+1);
if(tmp == NULL)
{
freeDATA(&p);
break;
}
if(!p.fstring) *tmp = '\0';
p.fstring = tmp;
strcat(p.fstring,buf);
}
fclose(fp);
if(p.fstring)
{
for(tmp = strtok(p.fstring,delim) ; tmp;
tmp = strtok(NULL,delim))
{
tmpp = realloc(p.pstring, (p.count+1)*sizeof(*tmpp));
if(tmpp == NULL)
{
freeDATA(&p);
break;
}
tmpp[p.count++] = tmp;
p.pstring = tmpp;
}
}
return p;
}

void freeDATA(DATA *p)
{
free(p->fstring);
free(p->pstring);
p->fstring = NULL;
p->pstring = NULL;
p->count = 0;
return;
}

void printDATA(DATA *p)
{
size_t i;

for(i = 0; i < p->count; i++)
printf("%u. %s\n",i,p->pstring[i]);
return;
}

--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #3

P: n/a
On 2 Apr 2004 17:31:23 -0800, go**********@hotmail.com (Goh, Yong
Kwang) wrote:
I'm trying to create a function that given a string, tokenize it and
put into a dynamically-sized array of char* which is in turn also
dynamically allocated based on the string token length.

I call the function using this code fragement in my main function:
---
char** arg_array;
arg_count = create_arg_array(command, argument, arg_array);
After you return from create_arg_array, arg_array has not been updated
with the address that was malloc'ed in the function. C always passes
by value.

for(count = 0; count < arg_count; count++)
printf("arg_array[%d]: %s\n", count, arg_array[count]);
---
And it always crashes with a segmentation fault when going into the
for loop to print out the array of strings. Why does it crash when
I've already called malloc and realloc (inside create_arg_array()
function) to reserve some memory for the string array?

The create_arg_array is given below.
What's wrong with this function?
---
size_t create_arg_array(char* file, char* arg, char** array){
size_t count;
char* argument;

count = 1;
/* 1 for the filename and 1 for the terminating NULL ptr. */
array = (char**) malloc(count * sizeof(char*));
Don't cast the return from malloc. It cannot help and can hurt.

array[0] = (char*) malloc(strlen(file) + 1);
strcpy((*array)[0], file);

if(arg != NULL){
argument = strtok(arg, " \n");
if(argument != NULL){
array = (char**) realloc(array, (count + 1) * sizeof(char*));
array[count] = (char*) malloc(strlen(argument) + 1);
strcpy(array[count], argument);
count++;
}
while((argument = strtok(NULL, " \n")) != NULL){
array = (char**) realloc(array, (count + 1) * sizeof(char*));
array[count] = (char*) malloc(strlen(argument) + 1);
strcpy(array[count], argument);
count++;
}
}
++count;
array = (char**) realloc(array, (count * sizeof(char*)));
array[count-1] = NULL;

return count-1; /* Minus 1 for the ending NULL */
}
---
I thought the address returned by realloc and malloc is lost when I
return to main function and I've also tried changing the function to
accept a pointer to the array of string (char***) but it doesn't help.
Yes it does if you use it properly. Your calling statement needs to
specify &arg_array. Inside the function, every place you currently
use array you need to use (*array). This will cause the function to
automatically update arg_array in the calling function.

Any advice appreciated.
Thank you.

Goh, Yong Kwang
Singapore
go**********@hotmail.com


<<Remove the del for email>>
Nov 14 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.