Click here to Skip to main content
15,886,017 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I would like to get your opinion on how to identify a segmentation fault problem in my code which is written in C language. I would share my code for your valuable comments,

Kindly regards

What I have tried:

C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <signal.h>
#include <assert.h>
#include <hiredis/hiredis.h>
#include <hiredis/async.h>
#include <hiredis/adapters/libevent.h>
#include <event.h>
#include <unistd.h>
#include <time.h>
#include <stdbool.h>
#define PACKETSIZE sizeof(cloudRANMessage)
#define COMMANDSIZE 256
 
typedef struct cloudRANMessage
{
    unsigned int      station_id;
    unsigned int      location_area;
    unsigned int      counterRedis;
    char              clientHostName[1024];
    char              command[COMMANDSIZE];
 
}cloudRANMessage;
 
char *accessKey;
char *accessHash;
 
void callbackDeserialize();
void serialize();
 
void printMyMessage(cloudRANMessage *message)
{
    printf("%d\n", message->location_area);
    printf("%d\n", message->station_id);
    printf("%s\n", message->command);
    printf("%s\n", message->counterRedis);
    printf("%s\n", message->clientHostName);
}
 
void serialize(cloudRANMessage *message, char *data)
{
    assert(data != NULL);
    memcpy(data, message, sizeof *message);
}
 
 
void deserialize(char *data, cloudRANMessage *tempMessage)
{
    memset(tempMessage, 0, sizeof(cloudRANMessage));
    memcpy(tempMessage, data, sizeof(cloudRANMessage));
    printMyMessage(tempMessage);
}
 
void deserializeLocal(char *data, cloudRANMessage *tempMessageLocal)
{
    memset(tempMessageLocal, 0, sizeof(cloudRANMessage));
    memcpy(tempMessageLocal, data, sizeof(cloudRANMessage));
    printMyMessage(tempMessageLocal);
}
 
void getCallback(redisAsyncContext *c, void *r, void *privdata)
{
    redisReply *reply = r;
    printf("%s\n", reply->str);                   // Call deserializaton function for the data retrieval.;
    /* Disconnect after receiving the reply to GET */
    redisAsyncDisconnect(c);
}
 
void replyParsing(void *reply)  // Parsing will be used to handle subscripton message reply to get the hash-key pair of the data that is written.
{
    redisReply *parsing = reply;
    printf("parsing array %s", parsing->element[2]->str);
    char *parsingArray = parsing->element[2]->str;
    char *p;
    p = strtok(parsingArray,"[ ""].");
    int i= 0;
    while(p !=NULL)
    {
        p = strtok(NULL,"[ ""].");
        if(i == 7)
        {
            accessHash = p;
            printf("%s\n",p);
        }
        else if(i == 8)
        {
            accessKey = p;
            printf("%s\n",p);
        }
    i++;
    }
     // send pointer here !
    // GET command here with the appropiate keys
}
// for the key hash value in the char. [8&9]
 
void listenChannel(redisAsyncContext *c, void *reply, void *privdata)
{
    struct event_base *base = (struct event_base*)privdata;
    char isExists = malloc(sizeof(isExists));
    isExists = "eNB";
    bool executeParsing = false;
    redisReply *r = reply;
    if (reply == NULL)
    return;
 
    printf("Client successfully subscribed to channel !\n");
    if(r->type == REDIS_REPLY_ARRAY){
 
        for(int j =0; j<r->elements;j++)
        {
            printf("Printing Redis Reply: %u) %s\n",j,r->element[j]->str);
            if (strstr(r->element[j]->str,isExists) != NULL)
                executeParsing = true;
            else
                executeParsing = false;
        }
 
    }
        if (executeParsing){
        replyParsing(r);
        printf("test received key !\n");
        event_base_loopexit(base,NULL);
    }
        else
        event_base_loopcontinue(base);
}
 
void callbackDeserialize(redisAsyncContext *c, void *r, cloudRANMessage *tempMessage) {
    redisReply *reply = r;
    if (reply == NULL) return;
    printf("%s\n", reply->str);                   // Call deserializaton function for the data retrieval.
    char *stringReply = reply->str;
    deserialize(stringReply, tempMessage);
    /* Disconnect after receiving the reply to GET */
    //
}
 
void callbackDeserializeLocal(redisAsyncContext *c, void *r, cloudRANMessage *tempMessageLocal) {
    redisReply *reply = r;
    if (reply == NULL) return;
    printf("%s\n", reply->str);                   // Call deserializaton function for the data retrieval.
    char *stringReply = reply->str;
    deserializeLocal(stringReply, tempMessageLocal);
    /* Disconnect after receiving the reply to GET */
    //
}
 
 
void connectCallback(const redisAsyncContext *c, int status) {
    if (status != REDIS_OK) {
        printf("Error: %s\n", c->errstr);
        return;
    }
    printf("Connected...\n");
}
 
void disconnectCallback(const redisAsyncContext *c, int status) {
    if (status != REDIS_OK) {
        printf("Error: %s\n", c->errstr);
        return;
    }
    printf("Disconnected...\n");
 
}
 
void connectCallback2(const redisAsyncContext *c2, int status) {
    if (status != REDIS_OK) {
        printf("Error: %s\n", c2->errstr);
        return;
    }
    printf("Connected...\n");
}
 
void disconnectCallback2(const redisAsyncContext *c2, int status) {
    if (status != REDIS_OK) {
        printf("Error: %s\n", c2->errstr);
        return;
    }
    printf("Disconnected...\n");
 
}
void connectCallback3(const redisAsyncContext *c3, int status) {
    if (status != REDIS_OK) {
        printf("Error: %s\n", c3->errstr);
        return;
    }
    printf("Connected...\n");
}
 
void disconnectCallback3(const redisAsyncContext *c3, int status) {
    if (status != REDIS_OK) {
        printf("Error: %s\n", c3->errstr);
        return;
    }
    printf("Disconnected...\n");
 
}
 
void exitCallback(redisAsyncContext *c, void *reply, void *privdata){
 
    struct event_base *base = (struct event_base*)privdata;
    event_base_loopexit(base,NULL);
}
 
int main (int argc, char **argv) {
 
    cloudRANMessage *cloudRANptr = malloc(sizeof(cloudRANMessage));
    cloudRANMessage *receivedMsg = malloc(sizeof(cloudRANMessage));
    cloudRANMessage *initialMessage = malloc(sizeof(cloudRANMessage));
    void *data = calloc(1,sizeof(cloudRANMessage));
 
    accessKey = malloc(sizeof(char));
    accessHash = malloc(sizeof(char));
 
    struct timeval start;
 
    initialMessage->location_area = 7214;
    initialMessage->station_id = 45632;
    initialMessage->counterRedis = 0;
    gethostname(initialMessage->clientHostName,1023);
    strcpy(initialMessage->command, "HANDOVER\0");
    gethostname(initialMessage->clientHostName,1023); // Gets the hostname of the compiled computer and puts in struct.
    printf("%s\n",initialMessage->clientHostName);
 
        signal(SIGPIPE, SIG_IGN);
        struct event_base *base = event_base_new();
        struct event_base *base3 = event_base_new();
        struct event_base *base2 = event_base_new();
        struct event_base *base4 = event_base_new();
 
        redisAsyncContext *localCon = redisAsyncConnect("localhost", 6379); // Connection will be used for get operation
        if (localCon->err) {
        printf("Error on localhost connection: %s\n", localCon->errstr);
        return 1;
        }
 
        redisAsyncContext *clientCon = redisAsyncConnect("192.168.1.103", 6379); // Connection will be used to write data on master
        if (clientCon->err) {
        printf("Error on master connection: %s\n", clientCon->errstr);
        return 1;
        }
 
        redisAsyncContext *subCon = redisAsyncConnect("localhost", 6379); // Connection will be used for SUBSCRIBE & UNSUBSCRIBE command
        if (subCon->err) {
        printf("Error on subscribe connection: %s\n", subCon->errstr);
        return 1;
        }
        unsigned int counter = malloc(sizeof(unsigned int));
        counter = 0;
 
        redisLibeventAttach(subCon, base2);
 
        redisAsyncSetConnectCallback(subCon,connectCallback3);
        redisAsyncSetDisconnectCallback(subCon,disconnectCallback3);
        counter++;
        redisAsyncCommand(subCon,listenChannel,base2,"SUBSCRIBE cloudRAN");
        WAITSUBSCRIBE:
        event_base_dispatch(base2);
        //initialize data on master !
        serialize(initialMessage,data);
        redisLibeventAttach(clientCon,base4);
        // Should run once to set the data !
        redisAsyncCommand(clientCon,exitCallback,base4,"HSET TA_1 eNB_1 %b",data,sizeof(cloudRANMessage));
 
        event_base_dispatch(base4);
 
        if(counter != 1){
        redisLibeventAttach(localCon, base);
        redisAsyncSetConnectCallback(localCon,connectCallback);
        redisAsyncSetDisconnectCallback(localCon,disconnectCallback);
        // Make an initial SET operation to the MASTER !
        // Access the data locally
 
        redisAsyncCommand(localCon,callbackDeserialize,receivedMsg,"HGET %s %s",accessHash,accessKey);
        printf("Execution in UNIX time for HGET:%ld\n", (start.tv_sec * 1000000 + start.tv_usec));
        event_base_loop(base,EVLOOP_ONCE);
        printf("Hash and Key value %s %s",accessHash,accessKey);
 
         if(initialMessage->clientHostName != receivedMsg->clientHostName){
 
            redisLibeventAttach(clientCon, base3);
 
            redisAsyncSetConnectCallback(clientCon,connectCallback2);
            redisAsyncSetDisconnectCallback(clientCon,disconnectCallback2);
 
            cloudRANptr = receivedMsg;   // Now access and change the data after verification
            cloudRANptr->counterRedis++;
            cloudRANptr->location_area= 56789; // Assign arbitrary location area value on this client
            serialize(cloudRANptr,data); // try with a different data pointer as well !!
            gettimeofday(&start, NULL);
            printf("Execution in UNIX time for HSET:%ld\n", (start.tv_sec * 1000000 + start.tv_usec));
            redisAsyncCommand(clientCon,exitCallback,base3,"HSET %s %s %b",accessHash,accessKey,data,sizeof(cloudRANMessage));
 
            event_base_dispatch(base3);
            goto WAITSUBSCRIBE;
        }
    }
        else
        goto WAITSUBSCRIBE;
    //redisAsyncCommand(c,NULL, NULL, "PUBLISH cloudRAN %b", data, sizeof(cloudRANMessage));
    return 0;
}
Posted
Updated 16-Oct-17 3:45am

It is too much code to inspect it for invalid pointers and indexes.

Two errors are here:
accessKey = malloc(sizeof(char));
accessHash = malloc(sizeof(char));
You probably want to use sizeof(char*) instead.
[EDIT]
Or don't allocate at all when only assigning pointers.

Another error is here:
printf("%s\n", message->counterRedis);
You have to use "%d" because message->counterRedis is of type int.
[/EDIT]

Some hints to find and/or detect such errors:

You should add assert statements to check all function pointer parameters for not being NULL.
Example (where you already had one check):
void serialize(cloudRANMessage *message, char *data)
{
    assert(message != NULL);
    assert(data != NULL);
    memcpy(data, message, sizeof *message);
}

You should initialise all variables. Example:
char *accessKey = NULL;
char *accessHash = NULL;

It might also help to add a length parameter to functions:
void serialize(cloudRANMessage *message, char *data, size_t data_buf_len)
{
    assert(message != NULL);
    assert(data != NULL);
    assert(data_buf_len >= sizeof(*message));
    memcpy(data, message, sizeof *message);
}

[EDIT]
Compile also with all warnings enabled (-Wall for most compilers). That might find some data type mismatches.
[/EDIT]

If you still got access violations, you have to use a debugger and step through your code.
 
Share this answer
 
v2
I would have expected isExists to be a pointer
C++
char isExists = malloc(sizeof(isExists));


Use the debugger, it will allow you to see where is the Segfaultabd to inspect variables, then you will have an idea of what is going on.

There is a tool that allow you to see what your code is doing, its name is debugger. It is also a great learning tool because it show you reality and you can see which expectation match reality.
When you don't understand what your code is doing or why it does what it does, the answer is debugger.
Use the debugger to see what your code is doing. Just set a breakpoint and see your code performing, the debugger allow you to execute lines 1 by 1 and to inspect variables as it execute.

Debugger - Wikipedia, the free encyclopedia[^]

Mastering Debugging in Visual Studio 2010 - A Beginner's Guide[^]
Basic Debugging with Visual Studio 2010 - YouTube[^]
The debugger is here to show you what your code is doing and your task is to compare with what it should do.
There is no magic in the debugger, it don't find bugs, it just help you to. When the code don't do what is expected, you are close to a bug.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900