Обсуждение: Why not use the calloc to replace malloc?

Поиск
Список
Период
Сортировка

Why not use the calloc to replace malloc?

От
Wen Yi
Дата:
HI team,
I'm a newbie to the postgres.
When I learn the code of libpq, the achieve of PQmakeEmptyPGresult, cause my  curiosity.

The old version code:
 
PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
{
      PGresult   *result;

      result = (PGresult *) malloc(sizeof(PGresult));
      if (!result)
            return NULL;

      result->ntups = 0;
      result->numAttributes = 0;
      result->attDescs = NULL;
      result->tuples = NULL;
      result->tupArrSize = 0;
      result->numParameters = 0;
      result->paramDescs = NULL;
      result->resultStatus = status;
      result->cmdStatus[0] = '\0';
      result->binary = 0;
      result->events = NULL;
      result->nEvents = 0;
      result->errMsg = NULL;
      result->errFields = NULL;
      result->errQuery = NULL;
      result->null_field[0] = '\0';
      result->curBlock = NULL;
      result->curOffset = 0;
      result->spaceLeft = 0;
      result->memorySize = sizeof(PGresult);
      /*
            .............
      */
      return result;
}

My version:

PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
{
      PGresult   *result;

      result = (PGresult *) calloc(sizeof(PGresult));
      if (!result)
            return NULL;

      result->memorySize = sizeof(PGresult);
      /*
            .............
      */
      return result;
}

Why not have a change?I don't know.
I'm a newbie, so I don't think I can commit a patch for postgres, just instead of send mail to ask.

Yours,
Wenyi.

Re: Why not use the calloc to replace malloc?

От
Tom Lane
Дата:
Wen Yi <chuxuec@outlook.com> writes:
> [ use calloc to replace zeroing fields individually ]

The reason we like to do it like that is that it provides greppability,
that is you can search the source code to see where a particular field
is initialized or modified.  The backend code is often intentionally
inefficient in this way: you can find a lot of places that do
makeNode(some-node-type) and then zero out fields within the node, even
though makeNode() always provides a zeroed-out struct.  An important
reason why this is a good idea is that the code isn't dependent on
whether the particular value you need to initialize the field to
happens to be bitwise zeros or something else.

People have complained about this practice off-and-on, but no one has
provided any evidence that there's a significant performance cost.
The maintenance benefits are real though.

            regards, tom lane



Re: Why not use the calloc to replace malloc?

От
Thorsten Glaser
Дата:
On Sat, 22 Apr 2023, Tom Lane wrote:

>Wen Yi <chuxuec@outlook.com> writes:
>> [ use calloc to replace zeroing fields individually ]
[…]
>People have complained about this practice off-and-on, but no one has
>provided any evidence that there's a significant performance cost.
>The maintenance benefits are real though.

Oh, interesting ;-) Thanks for this explanation.

Another data point is: calloc is not correct for pointer fields,
you have to manually assign NULL to them afterwards still, because
NULL doesn’t have to be represented by all-zero bytes (e.g. TenDRA
supports having 0x55555555 as NULL pointer as an option).

bye,
//mirabilos
--
15:41⎜<Lo-lan-do:#fusionforge> Somebody write a testsuite for helloworld :-)



Re: Why not use the calloc to replace malloc?

От
Tom Lane
Дата:
Thorsten Glaser <tg@evolvis.org> writes:
> On Sat, 22 Apr 2023, Tom Lane wrote:
>> The maintenance benefits are real though.

> Oh, interesting ;-) Thanks for this explanation.

> Another data point is: calloc is not correct for pointer fields,
> you have to manually assign NULL to them afterwards still, because
> NULL doesn’t have to be represented by all-zero bytes (e.g. TenDRA
> supports having 0x55555555 as NULL pointer as an option).

Yeah, according to the letter of the C standard you shouldn't assume
that NULL is physically the same as zero.  We've blithely ignored
that though --- there are lots of places that, for example, assume
that palloc0() of an array of pointers will produce pointer values
that are NULL.  I don't see any real-world benefit in insisting on
looping over such an array to set the pointers individually.

But this is a good comparison point, because it illuminates one
aspect of the maintenance argument.  Suppose you want to add a
field to struct Foo, and that field often or always needs to start
out with a nonzero value.  With our existing practice, grepping
for places that assign to the adjacent fields will generally find
all the places you need to touch.  If we relied more on calloc
or palloc0 to initialize fields, you'd have a harder time.  People
would be pushed into contorting their data representation choices
so that fields could start out as physically zero, and that would
lead to things like odd, inconsistent choices of boolean flag
polarity.

            regards, tom lane