I have a string creating function in C which accepts an array of structs as it's argument and outputs a string based on a predefined format (like a list of list in python).
Here's the function
typedef struct
{
    PacketInfo_t PacketInfo;
    char Gnss60[1900]; 
    //and other stuff...
} Track_json_t;
typedef struct 
{
    double latitude;
    double longitude;
} GPSPoint_t;
typedef struct
{
    UInt16          GPS_StatusCode;
    UInt32          fixtime;
    GPSPoint_t      point;
    double          altitude;
    unsigned char GPS_Satilite_Num;
} GPS_periodic_t;
unsigned short SendTrack()
{
    Track_json_t i_sTrack_S;
    memset(&i_sTrack_S, 0x00, sizeof(Track_json_t));
    getEvent_Track(&i_sTrack_S);
    //Many other stuff added to the i_sTrack_S struct...
    //Make a JSON format out of it
    BuildTrackPacket_json(&i_sTrack_S, XPORT_MODE_GPRS);
}
Track_json_t *getEvent_Track(Track_json_t *trk)
{
    GPS_periodic_t l_gps_60Sec[60];
    memset(&l_gps_60Sec, 0x00,
           sizeof(GPS_periodic_t) * GPS_PERIODIC_ARRAY_SIZE);
    getLastMinGPSdata(l_gps_60Sec, o_gps_base);
    get_gps60secString(l_gps_60Sec, trk->Gnss60);
    return trk;
}
void get_gps60secString(GPS_periodic_t input[60], char *output)
{
    int i = 0;
    memcpy(output, "[", 1); ///< Copy the first char as [
    char temp[31];
    for (i = 0; i < 59; i++) { //Run for n-1 elements
        memset(temp, 0, sizeof(temp));
        snprintf(temp, sizeof(temp), "[%0.8f,%0.8f],",
            input[i].point.latitude, input[i].point.longitude);
        strncat(output, temp, sizeof(temp));
    }
    memset(temp, 0, sizeof(temp)); //assign last element
    snprintf(temp, sizeof(temp), "[%0.8f,%0.8f]]",
             input[i].point.latitude, input[i].point.longitude);
    strncat(output, temp, sizeof(temp));
}
So the output of the function must be a string of format
[[12.12345678,12.12345678],[12.12345678,12.12345678],...]
But at times I get a string which looks like
[[12.12345678,12.12345678],[55.01[12.12345678,12.12345678],...]
[[21.28211567,84.13454083],[21.28211533,21.22[21.28211517,84.13454000],..]
Previously, I had a buffer overflow at the function get_gps60secString, I fixed that by using snprintf and strncat. 
Note: This is an embedded application and this error occur once or twice a day (out of 1440 packets)
Question
1. Could this be caused by an interrupt during the snprintf/strncat process?
2. Could this be caused by a memory leak, overwriting the stack or some other segmentation issue caused else where?
Basically I would like to understand what might be causing a corrupt string.
Having a hard time finding the cause and fixing this bug.
EDIT:
I used chux's function. Below is the Minimal, Complete, and Verifiable Example
/*
 * Test code for SO question https://stackoverflow.com/questions/5216413
 * A Minimal, Complete, and Verifiable Example
 */
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
typedef unsigned short UInt16;
typedef unsigned long  UInt32;
#define GPS_PERIODIC_ARRAY_SIZE  60
#define GPS_STRING_SIZE          1900
/* ---------------------- Data Structs --------------------------*/
typedef struct
{
    char Gnss60[GPS_STRING_SIZE];
} Track_json_t;
typedef struct
{
    double          latitude;
    double          longitude;
} GPSPoint_t;
typedef struct
{
    UInt16          GPS_StatusCode;
    UInt32          fixtime;
    GPSPoint_t      point;
    double          altitude;
    unsigned char GPS_Satilite_Num;
} GPS_periodic_t;
/* ----------------------- Global --------------------------------*/
FILE *fptr; //Global file pointer
int res = 0;
int g_last = 0;
GPS_periodic_t l_gps_60Sec[GPS_PERIODIC_ARRAY_SIZE];
/* ----------------------- Function defs --------------------------*/
/* At signal interrupt this function is called.
 * Flush and close the file. And safly exit the program */
void userSignalInterrupt()
{
    fflush(fptr);
    fclose(fptr);
    res = 1;
    exit(0);
}
/* @brief From the array of GPS structs we create a string of the format
 * [[lat,long],[lat,long],..]
 * @param   input   The input array of GPS structs
 * @param   output  The output string which will contain lat, long
 * @param   sz      Size left in the output buffer
 * @return  0       Successfully completed operation
 *          1       Failed / Error
 */
int get_gps60secString(GPS_periodic_t input[GPS_PERIODIC_ARRAY_SIZE], 
                       char *output, size_t sz) 
{
    int cnt = snprintf(output, sz, "[");
    if (cnt < 0 || cnt >= sz)
        return 1;
    output += cnt;
    sz -= cnt;
    int i = 0;
    for (i = 0; i < GPS_PERIODIC_ARRAY_SIZE; i++) {
        cnt = snprintf(output, sz, "[%0.8f,%0.8f]%s", 
                input[i].point.latitude, input[i].point.longitude, 
                i + 1 == GPS_PERIODIC_ARRAY_SIZE ? "" : ",");
        if (cnt < 0 || cnt >= sz)
            return 1;
        output += cnt;
        sz -= cnt;
    }
    cnt = snprintf(output, sz, "]");
    if (cnt < 0 || cnt >= sz)
        return 1;
    return 0; // no error
}
/* @brief   Create a GPS struct with data for testing. It will populate the
 * point field of GPS_periodic_t. Lat starts from 0.0 and increases by 1*10^(-8)
 * and Long will dstart at 99.99999999 and dec by 1*10^(-8)
 *
 * @param   o_gps_60sec Output array of GPS structs
 */
void getLastMinGPSdata(GPS_periodic_t *o_gps_60sec)
{
    //Fill in GPS related data here
    int i = 0;
    double latitude = o_gps_60sec[0].point.latitude;
    double longitude = o_gps_60sec[0].point.longitude;
    for (i = 0; i < 60; i++)
    {
        o_gps_60sec[i].point.latitude = latitude +  (0.00000001 * (float)g_last + 
                                        0.00000001 * (float)i);
        o_gps_60sec[i].point.longitude = longitude -  (0.00000001 * (float)g_last + 
                                        0.00000001 * (float)i);
    }
    g_last = 60;
}
/* @brief   Get the GPS data and convert it into a string
 * @param   trk Track structure with GPS string
 */
int getEvent_Track(Track_json_t *trk)
{
    getLastMinGPSdata(l_gps_60Sec);
    get_gps60secString(l_gps_60Sec, trk->Gnss60, GPS_STRING_SIZE);
    return 0;
}
int main()
{
    fptr = fopen("gpsAno.txt", "a");
    if (fptr == NULL) {
        printf("Error!!\n");
        exit(1);
    }
    //Quit at signal interrupt
    signal(SIGINT, userSignalInterrupt);
    Track_json_t trk;
    memset(&l_gps_60Sec, 0x00, sizeof(GPS_periodic_t) * GPS_PERIODIC_ARRAY_SIZE);
    //Init Points to be zero and 99.99999999
    int i = 0;
    for (i = 0; i < 60; i++) {
        l_gps_60Sec[i].point.latitude =  00.00000000;
        l_gps_60Sec[i].point.longitude = 99.99999999;
    }
    do {
        memset(&trk, 0, sizeof(Track_json_t));
        getEvent_Track(&trk);
        //Write to file
        fprintf(fptr, "%s", trk.Gnss60);
        fflush(fptr);
        sleep(1);
    } while (res == 0);
    //close and exit
    fclose(fptr);
    return  0;
}
Note: Error was not recreated in the above code.
Because this doesn't have the strcat pitfalls.
I tested this function in the embedded application.
Through this I was able to find that the snprintf returns an error and the string created ended up to be:
[17.42401750,78.46098717],[17.42402083,53.62
It ended there (because of the return 1). 
Does this mean that the data which was passed to snprints corrupted? It's a float value. How can it get corrupted?
Solution
The error have not been seen since I changed the sprintf function with one that doesn't directly deal with 64 bits of data.
Here's the function modp_dtoa2
/** \brief convert a floating point number to char buffer with a
 *         variable-precision format, and no trailing zeros
 *
 * This is similar to "%.[0-9]f" in the printf style, except it will
 * NOT include trailing zeros after the decimal point.  This type
 * of format oddly does not exists with printf.
 *
 * If the input value is greater than 1<<31, then the output format
 * will be switched exponential format.
 *
 * \param[in] value
 * \param[out] buf  The allocated output buffer.  Should be 32 chars or more.
 * \param[in] precision  Number of digits to the right of the decimal point.
 *    Can only be 0-9.
 */
void modp_dtoa2(double value, char* str, int prec)
{
    /* if input is larger than thres_max, revert to exponential */
    const double thres_max = (double)(0x7FFFFFFF);
    int count;
    double diff = 0.0;
    char* wstr = str;
    int neg= 0;
    int whole;
    double tmp;
    uint32_t frac;
    /* Hacky test for NaN
     * under -fast-math this won't work, but then you also won't
     * have correct nan values anyways.  The alternative is
     * to link with libmath (bad) or hack IEEE double bits (bad)
     */
    if (! (value == value)) {
        str[0] = 'n'; str[1] = 'a'; str[2] = 'n'; str[3] = '\0';
        return;
    }
    if (prec < 0) {
        prec = 0;
    } else if (prec > 9) {
        /* precision of >= 10 can lead to overflow errors */
        prec = 9;
    }
    /* we'll work in positive values and deal with the
       negative sign issue later */
    if (value < 0) {
        neg = 1;
        value = -value;
    }
    whole = (int) value;
    tmp = (value - whole) * pow10[prec];
    frac = (uint32_t)(tmp);
    diff = tmp - frac;
    if (diff > 0.5) {
        ++frac;
        /* handle rollover, e.g.  case 0.99 with prec 1 is 1.0  */
        if (frac >= pow10[prec]) {
            frac = 0;
            ++whole;
        }
    } else if (diff == 0.5 && ((frac == 0) || (frac & 1))) {
        /* if halfway, round up if odd, OR
           if last digit is 0.  That last part is strange */
        ++frac;
    }
    /* for very large numbers switch back to native sprintf for exponentials.
       anyone want to write code to replace this? */
    /*
      normal printf behavior is to print EVERY whole number digit
      which can be 100s of characters overflowing your buffers == bad
    */
    if (value > thres_max) {
        sprintf(str, "%e", neg ? -value : value);
        return;
    }
    if (prec == 0) {
        diff = value - whole;
        if (diff > 0.5) {
            /* greater than 0.5, round up, e.g. 1.6 -> 2 */
            ++whole;
        } else if (diff == 0.5 && (whole & 1)) {
            /* exactly 0.5 and ODD, then round up */
            /* 1.5 -> 2, but 2.5 -> 2 */
            ++whole;
        }
        //vvvvvvvvvvvvvvvvvvv  Diff from modp_dto2
    } else if (frac) {
        count = prec;
        // now do fractional part, as an unsigned number
        // we know it is not 0 but we can have leading zeros, these
        // should be removed
        while (!(frac % 10)) {
            --count;
            frac /= 10;
        }
        //^^^^^^^^^^^^^^^^^^^  Diff from modp_dto2
        // now do fractional part, as an unsigned number
        do {
            --count;
            *wstr++ = (char)(48 + (frac % 10));
        } while (frac /= 10);
        // add extra 0s
        while (count-- > 0) *wstr++ = '0';
        // add decimal
        *wstr++ = '.';
    }
    // do whole part
    // Take care of sign
    // Conversion. Number is reversed.
    do *wstr++ = (char)(48 + (whole % 10)); while (whole /= 10);
    if (neg) {
        *wstr++ = '-';
    }
    *wstr='\0';
    strreverse(str, wstr-1);
}
 
     
    