Hello I am working on a program that requires me to use structs. I am
allocating memory for the struct and the variables defined in them.
I am sure there is something incorrect with my code because there is
undefined behavior when running the program.


I am posting the code so if any of you can catch the problem.
I am new still to this so I am sure it's something trivial. I appreciate
any help.


Also are there any good guides/books that can get into more detailed
explanation of pointers and memory allocation so that I can have a more
in depth understanding?


Here is the code I am working with:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#define BUFFER_SIZ 128


typedef struct questionPacket
{
   char *id;
   char *data;
   char *choiceA;
   char *choiceB;
   char *choiceC;
   char *choiceD;
}qpacket;


typedef struct answerPacket
{
   char answer[1];
}anspacket;


void createQuestionPacket(struct questionPacket **qp);
void createAnswerPacket(struct answerPacket **ap);
void initializeSQLite();
int getQuestionPacket(struct questionPacket **qp);
static int getQuestionCallback(void *fpArg, int argc, char **argv, char
**azColName);


static sqlite3 *db;
static char *dbfile = "millionaire.db";
static int retval;
static char *zErrMsg = 0;
qpacket *callbackArg;


int main()
{
   qpacket   *qp;
   anspacket *ap;
    
   int ret = -1;
    
   /*test*/
   createQuestionPacket((struct questionPacket **)&callbackArg);
   /* allocate packet memory */
   createQuestionPacket((struct questionPacket **)&qp);
   createAnswerPacket((struct answerPacket **)&ap);
   initializeSQLite();
   printf("after initializeSQLite\n");
   ret = getQuestionPacket((struct questionPacket **)&qp);
   
   printf("id is %s\n",callbackArg->id);           /* id has correct 
value */
   printf("question is %s\n", callbackArg->data);  /* data has incorrect 
value */
   return 0;
}




void createQuestionPacket(struct questionPacket **qp)
{
   if((*qp=(struct questionPacket *)malloc(sizeof(qpacket)))==NULL)
   {
      fprintf(stderr, "No memory was allocated for change question packet!
\n");
      exit(0);
   }     
   (*qp)->id      = malloc(sizeof(char) * 8);
   (*qp)->data    = malloc(sizeof(char) * 256);
   (*qp)->choiceA = malloc(sizeof(char) * 128);
   (*qp)->choiceB = malloc(sizeof(char) * 128);
   (*qp)->choiceA = malloc(sizeof(char) * 128);
   (*qp)->choiceA = malloc(sizeof(char) * 128);
}




void createAnswerPacket(struct answerPacket **ap)
{
   if((*ap=(struct answerPacket *)malloc(sizeof(anspacket)))==NULL)
   {
      fprintf(stderr, "No memory was allocated for double dip packet!\n");
      exit(0);
   }
}


void initializeSQLite()
{
   /* connect to DB */
   retval = sqlite3_open_v2(dbfile, &db, SQLITE_OPEN_READWRITE, NULL);
   if( retval )
   {
      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
      sqlite3_close(db);
      exit(1);
   }
}


int getQuestionPacket(struct questionPacket **qp)
{
   char *questionSqlStmt;
   questionSqlStmt = malloc(BUFFER_SIZ);
   strcpy(questionSqlStmt,"select  
id,question,choice_a,choice_b,choice_c,"\
                              "choice_d from questionTbl ORDER BY "\
                                  "RANDOM
() LIMIT 1;");
   retval = sqlite3_exec(db, questionSqlStmt, getQuestionCallback, &qp, 
&zErrMsg);
    
   return retval;
}


static int getQuestionCallback(void *fpArg, int argc, char **argv, char 
**azColName)
{
   callbackArg = (struct questionPacket *)fpArg;
   strcpy(callbackArg->id,argv[0]);
   strcpy(callbackArg->data,argv[1]);
   /* uncommenting line below causes segmentation fault */
   /*strcpy(callbackArg->choiceA,argv[2]);
   strcpy(callbackArg->choiceB,argv[3]);
   strcpy(callbackArg->choiceC,argv[4]);
   strcpy(callbackArg->choiceD,argv[5]);*/
    
   return 0;
}