EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024 Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024
<== Date ==> <== Thread ==>

Subject: dblsr code question/challenge
From: Michael Davidsaver via Core-talk <core-talk at aps.anl.gov>
To: EPICS core-talk <core-talk at aps.anl.gov>
Date: Fri, 14 Jun 2024 17:45:00 -0700
A little C code "challenge" which puzzled me today.

Why was the following change a no-op?

As background.  For DB_LINK, the type stored in
'plink->value.pv_link.pvt' changed  from 'DBADDR*'
to 'dbChannel*' back with Base 3.15.0.1.  I was
quite surprised to notice that dblsr() was still
treating it as a 'DBADDR*'.I initially assumed
that no one had tested it since then.  But, after
thinking for awhile, I realized that the
situation was not so simple.

--- a/modules/database/src/ioc/db/dbLock.c
+++ b/modules/database/src/ioc/db/dbLock.c
@@ -918,7 +918,7 @@ long dblsr(char *recordname,int level)
                 pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[link]];
                 plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
                 if(plink->type != DB_LINK) continue;
-                pdbAddr = (DBADDR *)(plink->value.pv_link.pvt);
+                pdbAddr = &((dbChannel *)(plink->value.pv_link.pvt))->addr;

https://urldefense.us/v3/__https://github.com/epics-base/epics-base/commit/72d50ce2749bbc791907a32c1ed77af1333a21f5__;!!G_uCfscf7eWS!bqiRBiT_Ip0nrcLGxrmm1ZE6yiy1TzCcEIkBjZ30UI_daWaDnRhBenpKVMd1dyXCfbUXcYySljDXqZ16jZH7AIP8Qg$
... my answer below ...
















My key to understanding was noticing that the only usage
of 'pdbAddr' is to print the record name:

printf(" %s\n",pdbAddr->precord->name);

Now the most obvious answer would be if the struct dbAddr
embedded in the struct dbChannel were the first member.
However, this is not the case.

typedef struct dbChannel {
    const char *name;         /**< Channel name */
    dbAddr addr;              /**< Pointers to record & field */
...

The first member of dbAddr is the record pointer:

typedef struct dbAddr {
        struct dbCommon *precord;   /* address of record                     */

So

pdbAddr->precord->name

was actually accessing dbChannel::name with the correct
number of indirections (1) because 'precord->name' is not
actually an indirection since the first member is a 'char[]'.

typedef struct dbCommon {
    char                name[61];   /**< @brief Record Name */
...

So, I wasn't entirely truthful in calling this a no-op.
If a DB_LINK were targeted at a record alias name, then
between 3.15.0.1 and now, dblsr() would print the alias
instead of the intended canonical record name.

Now for the weekend!


Replies:
Re: dblsr code question/challenge Zimoch Dirk via Core-talk
Re: dblsr code question/challenge Kasemir, Kay via Core-talk

Navigate by Date:
Prev: Build failed: epics-base base-link-ext-1042 AppVeyor via Core-talk
Next: Build failed: epics-base base-improve_mingw_host_arch_check_msg-60 AppVeyor via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024
Navigate by Thread:
Prev: Build failed: epics-base base-link-ext-1042 AppVeyor via Core-talk
Next: Re: dblsr code question/challenge Zimoch Dirk via Core-talk
Index: 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  <2024
ANJ, 28 Jun 2024 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·