DJ-
DJ-

Reputation: 21

Weird segmentation fault while accessing string array

Sorry to post my project code directly. I've been trying to wrap my head around this weird seg fault which occurs at the line for(j=0; j<100 && *nnames[j] != (char *) NULL; j++). Isn't it legal to access a char** array this (*arr[]) way ?

    char** nnames = getcannames();
    char * new_str ;

    int j =0, len=0;
    ////////////////SEG FAULT HERE //////////////////
    for(j=0; j<100 && *nnames[j] != (char *) NULL; j++){
        len = len + strlen(nnames[j]);

    }
    if((new_str = (char*) malloc(len + 3)) != NULL){
        new_str[0] = '\0';   // ensures the memory is an empty string
        int i=0;    
        //setbuf(client_reply, NULL);
        for(i=0; i<7; i++){ //fix this, garbage values after index 68
            if(*nnames[i] == (char *) NULL) break;

            char *canname = strsave(nnames[i]);


            if( (find_newline = strchr( canname, NEWLINE )) != NULL )
                *find_newline = EOS;
            if(strcmp(canname, "!") != 0){
                strcat(new_str, canname);
                strcat(new_str, "\n");
            }

            //strcat(new_str, "\n\n");  
        }
        strcat(new_str,"\n\0");
        printf("%s", new_str);
        //strcpy( new_str, buf );
        buf = new_str;

    } else {
        perror("malloc failed!\n");
        // exit?
    }


char** getcannames(){
    //INITIALIZE
     char *names[100];
    int i;
    for(i=0; i<100; i++){
        names[i] = strsave("\0");
    }
    int namespos = 0;

     struct sym_list *sp;
     for( sp = Head.s_next;
     sp != (struct sym_list *) NULL;
     sp = sp->s_next )
    {
    if(getcannameindex(names, sp->s_sym.v_value) == -1){
        //strcpy(names[namespos++], sp->s_sym.v_name);
        names[namespos++] = strsave(sp->s_sym.v_value);
    }
    }
    return names;

}

Upvotes: 0

Views: 139

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

If nnames is a pointer to the first element of an array of pointers of type char * then the valid code will look like

for ( j = 0; j < 100 && nnames[j] != NULL; j++ ){
        len = len + strlen(nnames[j]);

provided that the last element of the array is a null pointer.

The same is valid for statement

if(*nnames[i] == (char *) NULL) break;

that is it has to be rewritten like

if ( nnames[i] == NULL ) break;

Also this function

char** getcannames(){
    //INITIALIZE
     char *names[100];

     //...

     return names;

}

has undefined behaviour because it returns pointer to the first element of a local array that will be destroyed after exiting the function.

Take into account that if function strsave creates dynamically a copy of the string passed to it as the argument

char *canname = strsave(nnames[i]);

then the program has memory leaks because you do not free canname.

And of course you may write like

strcat(new_str,"\n\0");

or even like

strcat(new_str,"\n\0\0\0\0");

but the both statements are equivalent to

strcat(new_str,"\n");

Upvotes: 4

Related Questions