简体   繁体   中英

How to memset for pointer-to-pointer

I've been trying to print value of protent structure.

struct protoent {
    char  *p_name;       /* official protocol name */
    char **p_aliases;    /* alias list */
    int    p_proto;      /* protocol number */
}

My code, following List.c, shows proto.p_name = (null) but It ends segmentation fault when it tries to print p_alliases .

Does anyone tell me how it happens?

I think memory isn't allocated to p_alliases pointer-to-pointer variable with memset or proto = { 0 }

Then how can I memset to p_aliases and print proto.p_aliases = (null) ?

List.c

#include <stdio.h>
#include <string.h>
#include <netdb.h>
int
main(){
        struct protoent proto  ;
        memset(&proto,0,sizeof(proto));
        printf("proto.p_name = %s\n",proto.p_name);
        printf("proto.p_aliases = %s\n",*proto.p_aliases);
        printf("proto.p_proto = %d\n",proto.p_proto);
}

The memset statment below is setting all the memory allocated by proto to 0 . So proto.p_aliases is pointing to 0x000000 then you're tring to dereference it which leads to segmentation fault.

memset(&proto,0,sizeof(proto));

*proto.p_aliases is the content of the adresse pointed to by proto.p_aliases so you cannot print it as the adresse is NULL . You can only print the adresse pointed to. So you have to change your print statment to:

printf("proto.p_aliases = %s\n", proto.p_aliases); // Not *proto.p_aliases

And because you're using the %s formating it will print (null) .

If you want to use memset with *proto.p_aliases then you have to allocate memory for it then proto.p_aliases is no longer pointing to NULL . In this case you can print. Then content of it's adresse.

    proto.p_aliases = malloc(sizeof(char *));
    memset(&(*proto.p_aliases), 0, sizeof(*proto.p_aliases));
    printf("*proto.p_aliases %s", *proto.p_aliases);

You are trying to dereference a null pointer (ie the member char **p_aliases ).

Enclosed is a print_array function that will safely print your array of strings, whether or not they have been assigned or freshly zeroed as in your example. The array is per the spec of protoent (ie null entry terminating the list).

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

struct protoent {
    char  *p_name;       /* official protocol name */
    char **p_aliases;    /* alias list */
    int    p_proto;      /* protocol number */
};

// print char *array[], final entry (s[n]==null), handles empty list (s==null) also
void print_array(char **s) {
    printf("[ ");
    for (int i = 0; s && s[i]; ++i)
        printf("\"%s\" ", s[i]);
    printf("]\n");
}

int main(){
        struct protoent proto  ;
        memset(&proto,0,sizeof(proto));

        printf("With freshly zeroed struct:\n");
        printf("proto.p_name = %s\n",proto.p_name);
        printf("proto.p_aliases = ");
        print_array(proto.p_aliases);
        printf("proto.p_proto = %d\n",proto.p_proto);

        char *aliases[] = { "A1", "A2", 0 };
        proto.p_aliases = aliases;
        printf("\nAfter assigning array:\n");
        printf("proto.p_aliases = ");
        print_array(proto.p_aliases);
}

Output:

$ ./nullstr 
With freshly zeroed struct:
proto.p_name = (null)
proto.p_aliases = [ ]
proto.p_proto = 0

After assigning array:
proto.p_aliases = [ "A1" "A2" ]

I hope this is helpful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM