d中的sqlite3压缩函数

时间:2015-09-02 05:16:20

标签: sqlite 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);
  }
}
}

可能导致问题的原因以及如何解决?

1 个答案:

答案 0 :(得分:3)

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传递&outBuf。使用sqlite3_free时,outBuf会尝试释放指向必须失败的局部变量jquery的指针。