D中的sqlite3压缩函数

sqlite3 compress function in D

我正在尝试调整 C 代码以在 D 中压缩来自 http://sqlite.1065341.n5.nabble.com/Compress-function-tp11998p11999.html 的数据但没有成功,当 运行 时给我 Segmentation fault (core dumped)。我已经尝试使用 gdb 对此进行调试,这似乎暗示我对 sqlite3_exec 的调用有问题,据我所知,它被正确使用了。

import etc.c.sqlite3, etc.c.zlib;

void main(){
  sqlite3* db;
  int rc;
  char* errmsg;

  rc = sqlite3_open(":memory:", &db);
  rc = sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, null, 
                               &sqlite_compress, null, null);
  rc = sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, null, 
                               &sqlite_decompress, null, null);
  rc = sqlite3_exec(db,
        "select decompress(compress('may the force be with you'))="
        "'may the force be with you'",
        null, null, &errmsg);
  assert(rc == SQLITE_OK);

  sqlite3_close(db);
}
extern(C){
static void sqlite_compress(sqlite3_context *context, int argc, sqlite3_value **argv){
  ulong rc, nIn, nOut;
  const(ubyte)* inBuf;
  ubyte* outBuf;

  inBuf = cast(ubyte*)sqlite3_value_blob(argv[0]);
  nIn = sqlite3_value_bytes(argv[0]);
  nOut = 13 + nIn + (nIn+999)/1000;
  outBuf = cast(ubyte*)sqlite3_malloc(cast(int)nOut+4);
  outBuf[0] = nIn>>24 & 0xff;
  outBuf[1] = nIn>>16 & 0xff;
  outBuf[2] = nIn>>8 & 0xff;
  outBuf[3] = nIn & 0xff;
  rc = compress(&outBuf[4], &nOut, inBuf, nIn);

  if( rc==Z_OK ){
    sqlite3_result_blob(context, &outBuf, cast(int)nOut+4, &sqlite3_free);
  }else{
    sqlite3_free(&outBuf);
    sqlite3_result_error(context, "uncompressable data", -1);
  }
}

static void sqlite_decompress(sqlite3_context *context, int argc, sqlite3_value **argv){
  ulong rc, nIn, nOut;
  const(ubyte)* inBuf;
  ubyte* outBuf;

  nIn = sqlite3_value_bytes(argv[0]);
  if( nIn<=4 )
    return;

  inBuf = cast(ubyte*)sqlite3_value_blob(argv[0]);
  nOut = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3];
  outBuf = cast(ubyte*)sqlite3_malloc( cast(int)nOut+1 );
  rc = uncompress(outBuf, &nOut, &inBuf[4], nIn);
  if( rc==Z_OK ){
    sqlite3_result_blob(context, outBuf, cast(int)nOut, &sqlite3_free);
  }else{
    sqlite3_free(&outBuf);
    sqlite3_result_error(context, "data is not compressed", -1);
  }
}
}

可能是什么原因导致了问题,我该如何解决?

sqlite_compress 中的这一行是罪魁祸首:

sqlite3_result_blob(context, &outBuf, cast(int)nOut+4, &sqlite3_free);

这是 sqlite_decompress 中的正确对应:

sqlite3_result_blob(context, outBuf, cast(int)nOut, &sqlite3_free);

注意到区别了吗?在 sqlite_compress 中,当您应该超过 outBuf 时,您却超过了 &outBuf。对于 &outBufsqlite3_free 尝试释放指向局部变量 outBuf 的指针,这肯定会失败。