www.digitalmars.com Home | Search | C & C++ | D | DMDScript | News Groups | index | prev | next
Archives

D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger

C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows

digitalmars.empire
digitalmars.DMDScript

c++ - Anybody tried compiling SQLite?

↑ ↓ ← Frank Albe <falbe mindspring.com> writes:
SQLite ( http://www.hwaci.com/sw/sqlite/ ) is a lightweight embeddable
SQL database engine. I'm trying to compile it to a library to static
link with Win32 console mode apps. 

It's 100% old-style C - the kind of code I used to write in the
eighties. It compiles cleanly, except I had to use "relaxed type
checking" on two of the modules. I'm currently stuck on a GPF (trying
to execute a function through a pointer which happens to be NULL. =:)

The pointer in question is in a table of function addresses that
_should_ resolve at link time, but all the pointers in the table are
NULL. To complicate matters, they are referenced through some
complicated #defines.

I'm wondering if anybody else has been through this particular
problem, which I think might involve linker options.

After I post this message I'm going to write a single module that has
a similar function table using the same #define tricks to see if I can
resolve it on my own.

Thanks for reading this. =:)

 ../frank
Jun 24 2003
Frank Albe <falbe mindspring.com> writes:
OK I found the culprit. I'm not sure it's legal C. The following
statements are all in one C source file.

There's a forward declaration like this:

 static BtOps sqliteBtreeOps;  
 // struct BtOps is a list of pointers to functions

then a little later on, an init function:

 int sqliteBtreeOpen( /* whatever */ ) {
    // lots of stuff including this statement
    pBt->pOps = &sqliteBtreeOps;
    // pBt is a pointer to a Btree structure
    // which contains pOps, a pointer to a BtOps structure
 }

Finally at the end of the module:

 static BtOps sqliteBtreeOps = {
    fileBtreeClose,
    // more function names
    // all functions are in this module
    };

The functions are executed from other modules using some clever
defines to make them look like normal function calls, but they amount
to calling pBt->pOps->functionName(arglist);


I wrote a minimal module to reproduce the problem. It also  GPFed with
the null pointer. All the function pointers in sqliteBtreeOps are 0.
If I comment out the forward declaration and move the init function
below the definition of sqliteBtreeOps, the function pointers are
valid and the minimal module works as expected.

If this is valid C, is there a compile or link option that will make
it work correctly?


Walter -  I can send you the little module if you think it's a
compiler bug.




On Tue, 24 Jun 2003 12:53:05 -0500, Frank Albe <falbe mindspring.com>
wrote:

SQLite ( http://www.hwaci.com/sw/sqlite/ ) is a lightweight embeddable
SQL database engine. I'm trying to compile it to a library to static
link with Win32 console mode apps. 

It's 100% old-style C - the kind of code I used to write in the
eighties. It compiles cleanly, except I had to use "relaxed type
checking" on two of the modules. I'm currently stuck on a GPF (trying
to execute a function through a pointer which happens to be NULL. =:)

The pointer in question is in a table of function addresses that
_should_ resolve at link time, but all the pointers in the table are
NULL. To complicate matters, they are referenced through some
complicated #defines.

I'm wondering if anybody else has been through this particular
problem, which I think might involve linker options.

After I post this message I'm going to write a single module that has
a similar function table using the same #define tricks to see if I can
resolve it on my own.

Thanks for reading this. =:)

 ../frank

../frank
Jun 24 2003
↑ ↓ "Walter" <walter digitalmars.com> writes:
Try reproducing it in a very small (10-20 lines) program. That'll usually
make it clear what is going on. -Walter
Jun 25 2003
↑ ↓ Frank Albe <falbe mindspring.com> writes:
On Wed, 25 Jun 2003 10:18:25 -0700, "Walter" <walter digitalmars.com>
wrote:

Try reproducing it in a very small (10-20 lines) program. That'll usually
make it clear what is going on. -Walter

I did that. I probably put too much detail in my second post. At the end of this post is the small program I wrote to reproduce the behavior. It has lots of comments that explain everything. I'm curious if it's valid C. This particular module treats another function pointer table exactly the same way. If it's valid C, is there a compiler or linker option get the module as written to work as intended? ----------------------------8< snip >8---------------------------- //============ code similar to sqlite btree.c module ========== typedef struct Btree Btree; typedef struct btOps btOps; // In real life this struct contains about 20 pointers to functions // which are defined later in the btree.c module. // struct btOps { int (*f1)(Btree*); }; // this struct defines a btree object. // struct Btree { btOps* btOp; }; // the following forward declaration and the init function are // near the beginning of the module. The program GPFs due to a // null pointer reference when trying to call bt.btOp->f1(&bt) // in main(). // // Comment out the forward declaration and this first // copy of initBtree() and uncomment the second copy // of initBtree() and it works because the function // pointers are correctly initialized. // static btOps BtreeOps; int initBtree( Btree* bt ) { bt->btOp = &BtreeOps; return 0; } // int f1( Btree* bt ) { return 0; } // this second delaration assigning values is at end of module. // when the forward declaration is in place, all the function // pointers are 0. When this is the ONLY definition, they are // valid addresses and it no longer GPFs // static btOps BtreeOps = { f1 }; // when initBtree() is below // the only declaration of BtreeOps, // the module works as expected. // //int initBtree( Btree* bt ) { // bt->btOp = &BtreeOps; // return 0; // } //========== sample user code ========== int main( int argc, char** argv ) { Btree bt; initBtree(&bt); bt.btOp->f1(&bt); return 0; } ----------------------------8< snip >8---------------------------- ../frank
Jun 25 2003
↑ ↓ "Walter" <walter digitalmars.com> writes:
Thanks, I can take it from here. -Walter
Jun 27 2003
↑ ↓ Frank Albe <falbe mindspring.com> writes:
On Fri, 27 Jun 2003 14:59:16 -0700, "Walter" <walter digitalmars.com>
wrote:

Thanks, I can take it from here. -Walter

Walter - Any progress? Here's a copy of the small program I've been using with each beta to determine if the problem is fixed. ------------------------8< beg >8------------------------ /* t1.c * test sqlite style function table */ typedef struct B B; typedef struct flist flist; struct flist { int (*f1)(B*); }; struct B { flist* flp; }; static flist funList; void showB( B* b ) { printf("b: %p:\n", b); printf(" b->flp: %p\n", (B*)b->flp); printf(" b->flp->f1: %p\n", (B*)b->flp->f1); } void initB( B* b ) { b->flp = &funList; showB(b); } int f1( B* b ) { return 0; } static flist funList = { f1 }; void testB( B* b ) { b->flp = &funList; showB(b); } int main( int argc, char** argv ) { B b; initB(&b); testB(&b); return 0; } ------------------------8< end >8------------------------ Results from Borland 5.5.1 (correct results): E>t1xbcc b: 0064FE00: b->flp: 0040A128 b->flp->f1: 004011C3 b: 0064FE00: b->flp: 0040A128 b->flp->f1: 004011C3 Results from 8.35.5n (note different addresses for b->flp and null address for first b->flp->f1): E>t1x b: 0063FDF4: b->flp: 0040AC04 b->flp->f1: 00000000 b: 0063FDF4: b->flp: 0040909C b->flp->f1: 00402058 ../frank
Aug 10 2003
↑ ↓ → "Walter" <walter digitalmars.com> writes:
"Frank Albe" <falbe mindspring.com> wrote in message
news:fkicjvsg8ud5jt82agn575tqgmnv4v0sn0 4ax.com...
 On Fri, 27 Jun 2003 14:59:16 -0700, "Walter" <walter digitalmars.com>
 wrote:

Thanks, I can take it from here. -Walter

Walter - Any progress?

Not yet. I'm putting out the next D release at the moment.
 Here's a copy of the small program I've been using with
 each beta to determine if the problem is fixed.

Thanks! Test cases are most appreciated.
Aug 10 2003
→ George Blat <georgeb brd.com> writes:
I did and only found very minor problems in trying to compile the
sqlite.dll. I did notice that the image size when compiled with
Digital Mars, Borland or Visual C++ is much larger that the binary
they offer, which comes from mingw.

I am using the latest beta for Digital Mars, and worked from the
IDDE.

I did not have a chance to see if it runs yet.

George Blat



Frank Albe wrote:
 SQLite ( http://www.hwaci.com/sw/sqlite/ ) is a lightweight embeddable
 SQL database engine. I'm trying to compile it to a library to static
 link with Win32 console mode apps. 
 
 It's 100% old-style C - the kind of code I used to write in the
 eighties. It compiles cleanly, except I had to use "relaxed type
 checking" on two of the modules. I'm currently stuck on a GPF (trying
 to execute a function through a pointer which happens to be NULL. =:)
 
 The pointer in question is in a table of function addresses that
 _should_ resolve at link time, but all the pointers in the table are
 NULL. To complicate matters, they are referenced through some
 complicated #defines.
 
 I'm wondering if anybody else has been through this particular
 problem, which I think might involve linker options.
 
 After I post this message I'm going to write a single module that has
 a similar function table using the same #define tricks to see if I can
 resolve it on my own.
 
 Thanks for reading this. =:)
 
  ../frank

Jun 25 2003
→ George Blat <georgeb brd.com> writes:
I did and only found very minor problems in trying to compile the
sqlite.dll. I did notice that the image size when compiled with
Digital Mars, Borland or Visual C++ is much larger that the binary
they offer, which comes from mingw.

I am using the latest beta for Digital Mars, and worked from the
IDDE.

I did not have a chance to see if it runs yet.

George Blat



Frank Albe wrote:
 SQLite ( http://www.hwaci.com/sw/sqlite/ ) is a lightweight embeddable
 SQL database engine. I'm trying to compile it to a library to static
 link with Win32 console mode apps. 
 
 It's 100% old-style C - the kind of code I used to write in the
 eighties. It compiles cleanly, except I had to use "relaxed type
 checking" on two of the modules. I'm currently stuck on a GPF (trying
 to execute a function through a pointer which happens to be NULL. =:)
 
 The pointer in question is in a table of function addresses that
 _should_ resolve at link time, but all the pointers in the table are
 NULL. To complicate matters, they are referenced through some
 complicated #defines.
 
 I'm wondering if anybody else has been through this particular
 problem, which I think might involve linker options.
 
 After I post this message I'm going to write a single module that has
 a similar function table using the same #define tricks to see if I can
 resolve it on my own.
 
 Thanks for reading this. =:)
 
  ../frank

Jun 25 2003