-1

The program crashes when printing the timestamp. I believe the error is located in the function void flightRec_PrflightRecData(flightRecRead* thisFlight) which is designed to do three things:

  1. declare the time struct flighttime, flighttime is in POSIX format.
  2. Localtime converts the POSIX time to a human-readable time.
  3. The fourth specifier prints the converted time using asctime which prints it in Www Mmm dd hh:mm:ss yyyy format.

The error is tb != NULL and shows other information specifying asctime.

What I have done to troubleshoot:

  1. Check for time header
  2. Checked pointers and addresses
  3. Turned deprecation off
  4. Checked the format specifier

Any assistance is appreciated.

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


typedef struct flightRec_struct { // declare a struct to match the format of the binary data
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
} flightRec;

typedef struct flightRecRead_struct { // declare a struct to match the format of your linked list
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
    struct flightRec* nextFlight_ptr;
} flightRecRead;



// Print dataVal
void flightRec_PrflightRecData(flightRecRead* thisFlight) {
    struct tm *flightTime;
    flightTime = localtime(&thisFlight->timestamp);
    printf("%s \t %s \t %s \t %s\n", thisFlight->FlightNum, thisFlight->OriginAirportCode,
        thisFlight->DestAirportCode, asctime(flightTime));
    return;
}

// Grab location pointed by nextFlight_ptr
flightRecRead* flightRec_GetNext(flightRecRead* thisFlight) {
    return thisFlight->nextFlight_ptr;
}

int main(void) {
    flightRec firstStruct;
    flightRecRead* headObj = NULL;
    flightRecRead* currObj = NULL;
    flightRecRead* tailObj = NULL;
    struct tm *flightTime;
    int i = 0;                               //loop index


    FILE* inFile = NULL;
    inFile = fopen("acars.bin", "rb");
    if (inFile == NULL) {
        printf("Could not open file acars.bin.\n");
        return -1;
    }

    if (!feof(inFile)) {
        fread(&firstStruct, sizeof(flightRec), 1, inFile); // 2. read the file into that struct

        headObj = (flightRecRead*)malloc(sizeof(flightRecRead)); // 3. make head point to that struct
        strcpy(headObj->FlightNum, firstStruct.FlightNum);
        strcpy(headObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(headObj->DestAirportCode, firstStruct.DestAirportCode);
        headObj->timestamp = firstStruct.timestamp;

        tailObj = (flightRecRead*)malloc(sizeof(flightRecRead));  // 4. make tail point to that struct
        strcpy(tailObj->FlightNum, firstStruct.FlightNum);
        strcpy(tailObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(tailObj->DestAirportCode, firstStruct.DestAirportCode);
        tailObj->timestamp = firstStruct.timestamp;
        headObj->nextFlight_ptr = tailObj;
        tailObj->nextFlight_ptr = NULL;
    }

    while (!feof(inFile)) {                       // 5. while not end-of-file on the acars file:
        fread(&firstStruct, sizeof(flightRec), 1, inFile); // 6. malloc a new struct
        currObj = (flightRecRead*)malloc(sizeof(flightRecRead));
        strcpy(currObj->FlightNum, firstStruct.FlightNum);
        strcpy(currObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(currObj->DestAirportCode, firstStruct.DestAirportCode);
        currObj->timestamp = firstStruct.timestamp;
        currObj->nextFlight_ptr = NULL;

        tailObj->nextFlight_ptr = currObj;
        tailObj = currObj;
    }


    currObj = headObj;                           // Print the list
    printf("FlightNum \t OriginAirportCode \t DestAirportCode \t Time \t \n");
    while (currObj != NULL) {
        flightRec_PrflightRecData(currObj);
        currObj = flightRec_GetNext(currObj);
    }

    system("pause"); //return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Airfire29
  • 1
  • 2
  • 1
    Please clarify your question. "The error is tb != NULL". That's not clear. There is no `tb` in your source code. – kaylum Apr 29 '15 at 03:44
  • Yes, my question is why is the timestamp not printing in asctime format. I believe the code instruction in the flightRec_PrflightRecData function 1. gets the flight in the struct read 2. converts it to local time 3. prints it using asctime. – Airfire29 Apr 29 '15 at 03:48
  • Please, be more precise in your information and question. What does "timestamp not printing in asctime format" mean? It crashes? It prints 0? It prints nothing? It prints the time in the wrong format? Or?? Tell us exactly what the input is, what the expected output is and what the actual output is. And please update the actual question description with this information so that it makes sense instead of adding info to the comments. – kaylum Apr 29 '15 at 03:52
  • Noted Alan Au, thank you. – Airfire29 Apr 29 '15 at 04:06
  • Is anyone out there? – Airfire29 Apr 29 '15 at 04:24

1 Answers1

1

When I compile your code on a 64-bit Mac with GCC 5.1.0, it gives me a number of errors. Some of them, though, are consequences of the very stringent compilation options I use:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -Werror timecrash.c -o timecrash
timecrash.c:25:6: error: no previous prototype for ‘flightRec_PrflightRecData’ [-Werror=missing-prototypes]
 void flightRec_PrflightRecData(flightRecRead* thisFlight) {
      ^
timecrash.c: In function ‘flightRec_PrflightRecData’:
timecrash.c:27:28: error: passing argument 1 of ‘localtime’ from incompatible pointer type [-Werror=incompatible-pointer-types]
     flightTime = localtime(&thisFlight->timestamp);
                            ^
In file included from timecrash.c:4:0:
/usr/include/time.h:112:12: note: expected ‘const time_t * {aka const long int *}’ but argument is of type ‘int *’
 struct tm *localtime(const time_t *);
            ^
timecrash.c: At top level:
timecrash.c:34:16: error: no previous prototype for ‘flightRec_GetNext’ [-Werror=missing-prototypes]
 flightRecRead* flightRec_GetNext(flightRecRead* thisFlight) {
                ^
timecrash.c: In function ‘flightRec_GetNext’:
timecrash.c:35:12: error: return from incompatible pointer type [-Werror=incompatible-pointer-types]
     return thisFlight->nextFlight_ptr;
            ^
timecrash.c: In function ‘main’:
timecrash.c:68:33: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
         headObj->nextFlight_ptr = tailObj;
                                 ^
timecrash.c:81:33: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
         tailObj->nextFlight_ptr = currObj;
                                 ^
timecrash.c:44:9: error: unused variable ‘i’ [-Werror=unused-variable]
     int i = 0;                               //loop index
         ^
timecrash.c:43:16: error: unused variable ‘flightTime’ [-Werror=unused-variable]
     struct tm *flightTime;
                ^
cc1: all warnings being treated as errors
$

The 'unused variables' and 'no previous prototype' errors (would be warnings except that I used -Werror to force all warnings to be treated as errors).

But the misuse of int as a surrogate for time_t could be a problem for you too. It may be less of an issue if you compile for a 32-bit platform.

The other 'incompatible pointer type' warnings are worrying, too. In fact, your second structure definition is incorrect. You have:

typedef struct flightRec_struct {
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
} flightRec;

typedef struct flightRecRead_struct {
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
    struct flightRec* nextFlight_ptr;
} flightRecRead;

The struct flightRec * is a pointer to an incomplete type. It is not a struct flightRec_struct nor a flightRec (nor a struct flightRecRead_struct nor a flightRecRead). In fact, you need it to be either a struct flightRecRead_struct * or you need to predeclare the type and use a flightRecRead *:

typedef struct flightRecRead_struct flightRecRead;
struct flightRecRead_struct {
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
    flightRecRead *nextFlight_ptr;
};

You could simplify the assignment part of your code by using:

struct flightRecRead_struct
{
    flightRec      flight;
    flightRecRead *nextFlight_ptr;
};

You could then assign the entire flightRec structure in a single line, rather than having to write out the multiple strcpy() operations, etc.

Against this, if you need to use time_t and that is not the same size as an int and the binary format is fixed externally, then you may need to do the member-wise copying after all.

You should learn why while (!feof(file)) is always wrong.


Semi-fixed code: timecrash.c

This code more or less works for me.

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

typedef struct flightRec_struct
{
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    time_t timestamp;
} flightRec;

typedef struct flightRecRead_struct flightRecRead;
struct flightRecRead_struct
{
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    time_t timestamp;
    flightRecRead *nextFlight_ptr;
};

static
void flightRec_PrflightRecData(flightRecRead *thisFlight)
{
    struct tm *flightTime = localtime(&thisFlight->timestamp);
    printf("timestamp = 0x%.8lX\n", (long)thisFlight->timestamp);
    assert(flightTime != 0);
    printf("%s \t %s \t %s \t %s\n", thisFlight->FlightNum, thisFlight->OriginAirportCode,
           thisFlight->DestAirportCode, asctime(flightTime));
}

static
flightRecRead *flightRec_GetNext(flightRecRead *thisFlight)
{
    return thisFlight->nextFlight_ptr;
}

int main(void)
{
    flightRec firstStruct;
    flightRecRead *headObj = NULL;
    flightRecRead *currObj = NULL;
    flightRecRead *tailObj = NULL;
    const char filename[] = "acars.bin";
    int recnum = 0;
    FILE *inFile = fopen(filename, "rb");

    if (inFile == NULL)
    {
        fprintf(stderr, "Could not open file %s.\n", filename);
        return -1;
    }

    if (fread(&firstStruct, sizeof(flightRec), 1, inFile) == 1)
    {
        printf("Record %d\n", ++recnum);
        headObj = (flightRecRead *)malloc(sizeof(flightRecRead));
        strcpy(headObj->FlightNum, firstStruct.FlightNum);
        strcpy(headObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(headObj->DestAirportCode, firstStruct.DestAirportCode);
        headObj->timestamp = firstStruct.timestamp;
        flightRec_PrflightRecData(headObj);

        tailObj = (flightRecRead *)malloc(sizeof(flightRecRead));
        strcpy(tailObj->FlightNum, firstStruct.FlightNum);
        strcpy(tailObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(tailObj->DestAirportCode, firstStruct.DestAirportCode);
        tailObj->timestamp = firstStruct.timestamp;
        flightRec_PrflightRecData(tailObj);

        headObj->nextFlight_ptr = tailObj;
        tailObj->nextFlight_ptr = NULL;
    }

    while (fread(&firstStruct, sizeof(flightRec), 1, inFile) == 1)
    {
        printf("Record %d\n", ++recnum);
        currObj = (flightRecRead *)malloc(sizeof(flightRecRead));
        strcpy(currObj->FlightNum, firstStruct.FlightNum);
        strcpy(currObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(currObj->DestAirportCode, firstStruct.DestAirportCode);
        currObj->timestamp = firstStruct.timestamp;
        currObj->nextFlight_ptr = NULL;
        flightRec_PrflightRecData(currObj);

        tailObj->nextFlight_ptr = currObj;
        tailObj = currObj;
    }
    printf("Finished reading\n");

    currObj = headObj;
    printf("FlightNum \t OriginAirportCode \t DestAirportCode \t Time \t \n");
    recnum = 0;
    while (currObj != NULL)
    {
        printf("Record %d\n", ++recnum);
        flightRec_PrflightRecData(currObj);
        currObj = flightRec_GetNext(currObj);
    }

    fclose(inFile);

    system("pause");
}

Sample run

The data generation assumes time_t is a 64-bit type aligned on an 8-byte boundary (7 null padding bytes before it), and is formatted in little-endian (as on Intel).

$ printf "BA7231\0LHR\0\0LGW\0\0\0\0\0\0\0\0\0\xA2\x93\x84\x75\0\0\0\0" > acars.bin
$ printf "UA9240\0LAX\0\0AMS\0\0\0\0\0\0\0\0\0\x72\x93\x84\x75\0\0\0\0" >> acars.bin
$ odx acars.bin
0x0000: 42 41 37 32 33 31 00 4C 48 52 00 00 4C 47 57 00   BA7231.LHR..LGW.
0x0010: 00 00 00 00 00 00 00 00 A2 93 84 75 00 00 00 00   ...........u....
0x0020: 55 41 39 32 34 30 00 4C 41 58 00 00 41 4D 53 00   UA9240.LAX..AMS.
0x0030: 00 00 00 00 00 00 00 00 72 93 84 75 00 00 00 00   ........r..u....
0x0040:
$ ./timecrash
Record 1
timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

Record 2
timestamp = 0x75849372
UA9240   LAX     AMS     Wed Jun 23 09:59:30 2032

Finished reading
FlightNum    OriginAirportCode   DestAirportCode     Time    
Record 1
timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

Record 2
timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

Record 3
timestamp = 0x75849372
UA9240   LAX     AMS     Wed Jun 23 09:59:30 2032

^C
$

The interrupt was necessary because my pause on Mac OS X doesn't terminate until interrupted (or otherwise sent a signal).

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278