Thread overview
Anybody tried compiling SQLite?
Jun 24, 2003
Frank Albe
Jun 25, 2003
Frank Albe
Jun 25, 2003
Walter
Jun 25, 2003
Frank Albe
Jun 27, 2003
Walter
Aug 10, 2003
Frank Albe
Aug 11, 2003
Walter
Jun 26, 2003
George Blat
Jun 26, 2003
George Blat
June 24, 2003
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
June 25, 2003
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
June 25, 2003
Try reproducing it in a very small (10-20 lines) program. That'll usually make it clear what is going on. -Walter


June 25, 2003
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
June 26, 2003
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

June 26, 2003
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

June 27, 2003
Thanks, I can take it from here. -Walter


August 10, 2003
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
August 11, 2003
"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.