0

I am using PostgreSql C library libpq, and I can fetch values from the PGresult pointer with PQgetvalue function.

Now, I have a table with 10-20 columns, and I want to print them out with a simple printf call:

printf("%s,%s,%s..(so on...)...%s", resA, resB, resC,..., resN);

where resA to resB are strings loaded using PGgetvalue function. Now, this approach requires 10-20 pointers declared (if I want to print it out with a single printf), and I was going to use something simple as:

char* getFieldVal(PGresult* res, int row, char* fieldName)
{
    static char tmp[1000];
    memset(tmp, 0, sizeof(tmp));

    // Load data here...

    return tmp;
}

and then to call printf like:

printf("%s,%s,%s..(so on...)...%s", 
       getField(r, 0, "A"), getField(r, 0, "B"), ... , getField(r, 0, "N"));

However, output of the printf function is indicating that all getField calls are returning whatever first was requested from the database (in this case, value of the A field), even though I've deleted the previous string (just to be sure) with memset call.

Where am I wrong? Is something in my code, or is gcc assuming that all my getField calls returns pointer to the same memory, so it is not actually calling it mulitple times.

Or, is printf function first evaluating all parameters (in reverse order), and then actually calling the function? If this is the case (and I bet it is), is there any simpler pattern to achieve what I am trying?

Nemanja Boric
  • 21,627
  • 6
  • 67
  • 91
  • If I am not wrong because you are using static array and calling in printf() Is it not undefined behavior in C? – Grijesh Chauhan Apr 02 '13 at 18:36
  • The point is you _are_ returning a pointer to the same memory, and so whatever's there after the last expression is evaluated is printed three times. – teppic Apr 02 '13 at 18:41
  • Yes, I though this is the case (see my last paragraph). That actually make sense, because before calling the function, all parameters must be evaluated. – Nemanja Boric Apr 02 '13 at 18:45
  • 1
    A solution is to pass an allocated array to the function (a separate one for each), and have it modify that array and return it. There's no memory leak or need to call `printf` separately then. – teppic Apr 02 '13 at 18:50

2 Answers2

1

You're simply returning the address of a static/global variable in this function, so each time you call it, the data is overwritten and the same pointer is returned.

One simpler way of doing this is by looping over the data set and printing each variable separately instead of in a formatted string.

Eddy Luten
  • 432
  • 2
  • 11
1

Or, is printf function first evaluating all parameters (in reverse order), and then actually calling the function?

Yes.

But there's no need to copy the results since they persist in memory until PQclear(PGresult*) is called.

Starting from your function, you may get the pointer to the value of fieldName for row with:

char* getFieldVal(PGresult* res, int row, char* fieldName)
{
  int n = PQfnumber(res, fieldName);
  if (n == -1)
    return NULL; /* missing field, you might prefer to return an empty string here */
  else
    return PQgetvalue(res, row, n);
}
Daniel Vérité
  • 58,074
  • 15
  • 129
  • 156