1

I have defined a structure, and this is the example code:

typedef struct {
    char *like;
    int age;
    int class;
} info_t;

typedef struct {
    info_t *tom;
    info_t *jack;
} student;

If I call this structure without applying for memory space, I will encounter a segment error.

The code like this:

sutdent *s1;

s1->tom->like = "play game";

So is there a way to check if the member that needs to be called is available before calling the structural member?

I made an attempt like this:

if(s1) {
    if(s1->tom) {
        s1->tom->like = "play game";
    }
}

But this is not always effective, because if the pointer does not manually point to an NULL address, it may point anywhere.


That's it. I'm building a network library, which is the definition of a structure. Due to the possibility that this library will be open source in the future, and if users execute the memory release function in this library without applying for memory space in advance, unexpected problems may occur.

typedef struct {
    SOCKADDR *client;
    SOCKADDR *receiver;
    snSize size;
} snNetInfo_t;

typedef struct {
    snNetSocket sockfd;       // sizeof: win[8], linux[4]
    sn_u32      sockfdFamily; // sizeof: 4
    snNetType   sockfdType;   // sizeof: win[4], linux[8]
    snNetInfo_t *info;        // sizeof: 8
} snNet_ctx;

SN_PUBLIC(snError) snNet_malloc_init SN_OPEN_API SN_FUNC_OF(
    (snNet_ctx **ctx, sn_u32 family)
) {
    if(!((*ctx) = (snNet_ctx *)malloc(sizeof(snNet_ctx)))) {
        // If the memory request for the snNet object fails
        return snErr_Memory;
    }
    if(!((*ctx)->info  = (snNetInfo_t *)malloc(sizeof(snNetInfo_t)))) {
        // If the memory request for the info member of the snNet object fails
        return snErr_Memory;
    }
    if(family == AF_INET) {
        (*ctx)->sockfdFamily = AF_INET;
        (*ctx)->info->size = SN_NET_IPV4_ADDR_SIZE;
    } else if(family == AF_INET6) {
        (*ctx)->sockfdFamily = AF_INET6;
        (*ctx)->info->size = SN_NET_IPV6_ADDR_SIZE;
    } else {
        // If it is neither IPv4 nor IPv6
        return snErr_NetFamily;
    }
    (*ctx)->info->receiver = (SOCKADDR *)malloc((*ctx)->info->size);
    (*ctx)->info->client = (SOCKADDR *)malloc((*ctx)->info->size);
    if(!(*ctx)->info->receiver || !(*ctx)->info->client) {
        // If the memory application for receiving or client information fails
        return snErr_Memory;
    }
    return snErr_OK;
}

SN_PUBLIC(snError) snNet_release SN_OPEN_API SN_FUNC_OF(
    (snNet_ctx **ctx)
) {
    if((*ctx)) {
        if((*ctx)->info) {
            if((*ctx)->info->receiver)
                free((*ctx)->info->receiver);
            if((*ctx)->info->client)
                free((*ctx)->info->client);
            free((*ctx)->info);
        }
        free((*ctx));
        (*ctx) = snNull;
    }
    return snErr_OK;
}
S-N
  • 306
  • 10
  • You have lots of pointers in your code, but none of them are initialized, so they can contain whatever garbage value. Either just dont use pointers (you probably dont need them in this case), or you have to allocate memory for each of them like e.g. `student *s1 = (student*)malloc(sizeof(student));`. If you want to check your pointers, you can do it like `if(somePointer)` or `if(somePointer != NULL)`, but again, you would have to initialize them first with eiter `student *s1 = NULL;` or by allocation memory for them. – Joel May 07 '23 at 13:25
  • 1
    Short answer: no if you don't initialize them to NULL. – m0skit0 May 07 '23 at 13:26
  • 3
    This is the joy of C. You can't know if a pointer is valid or not. It is up to you to write code that is safe by always making sure to initialize pointers to NULL or something valid. – Retired Ninja May 07 '23 at 13:26
  • 1
    There's no way that's *always effective*. In the general case a C compiler cannot prove that a pointer doesn't point to garbage (though it's quite evident in your example) -- there might be complex control flow where only in some paths the pointer gets correctly initialized. And trying to write to it it doesn't show it either. The garbage might just be a function's return address for example, which tends to be perfectly writable, but then you'll be returning to some garbage place (=> undefined behavior is undefined). – Petr Skocik May 07 '23 at 13:32
  • 2
    BTW, you shouldnt really write your own identifiers ending with `_t`. [see this posts answers](https://stackoverflow.com/q/231760/20785822). – Joel May 07 '23 at 13:35
  • @Joel I actually care about this issue, but because the code is currently closed source, there is no need to worry about this issue temporarily. – S-N May 07 '23 at 13:42

0 Answers0