Итератор LevelDB C

Мне нужно выполнить итерацию через базу данных leveldb на языке c – https://github.com/google/leveldb/blob/master/include/leveldb/ch . Все работает, кроме итерации. Результат идет с некоторыми данными двоичного шума:

key: value1 key: value2 key#&^$&*# value one1(*@(# value1 two2%*@( value2 

С символами $ & * # и т. Д. Я показал двоичный вывод, stackoverflow не позволяет помещать здесь двоичный вывод.

Код:

 #include  #include  int main() { leveldb_t *db; leveldb_options_t *options; leveldb_readoptions_t *roptions; leveldb_writeoptions_t *woptions; char *err = NULL; char *read; size_t read_len; /******************************************/ /* OPEN */ options = leveldb_options_create(); leveldb_options_set_create_if_missing(options, 1); db = leveldb_open(options, "testdb", &err); if (err != NULL) { fprintf(stderr, "Open fail.\n"); return(1); } /* reset error var */ leveldb_free(err); err = NULL; /******************************************/ /* WRITE */ woptions = leveldb_writeoptions_create(); leveldb_put(db, woptions, "one", 3, "value1", 6, &err); if (err != NULL) { fprintf(stderr, "Write fail.\n"); return(1); } leveldb_free(err); err = NULL; /******************************************/ /* WRITE 2 */ woptions = leveldb_writeoptions_create(); leveldb_put(db, woptions, "two", 3, "value2", 6, &err); if (err != NULL) { fprintf(stderr, "Write fail.\n"); return(1); } leveldb_free(err); err = NULL; /******************************************/ /* READ */ roptions = leveldb_readoptions_create(); read = leveldb_get(db, roptions, "one", 3, &read_len, &err); if (err != NULL) { fprintf(stderr, "Read fail.\n"); return(1); } printf("key: %s\n", read); leveldb_free(err); err = NULL; /******************************************/ /* READ 2 */ roptions = leveldb_readoptions_create(); read = leveldb_get(db, roptions, "two", 3, &read_len, &err); if (err != NULL) { fprintf(stderr, "Read fail.\n"); return(1); } printf("key: %s\n", read); leveldb_free(err); err = NULL; /******************************************/ /* ITERATE */ roptions = leveldb_readoptions_create(); leveldb_iterator_t *iter = leveldb_create_iterator(db, roptions); for (leveldb_iter_seek_to_first(iter); leveldb_iter_valid(iter); leveldb_iter_next(iter)) { size_t key_len, value_len; const char *key_ptr = leveldb_iter_key(iter, &key_len); const char *value_ptr = leveldb_iter_value(iter, &value_len); /* Prints some binary noise with the data */ printf("%s %s\n", key_ptr, value_ptr); } leveldb_iter_destroy(iter); leveldb_free(err); err = NULL; /******************************************/ /* CLOSE */ leveldb_close(db); return(0); } 

Как правильно выполнить итерацию через LevelDB в C?

    Кажется, что значения, возвращаемые leveldb_iter_key и leveldb_iter_value , не соответствуют leveldb_iter_key с leveldb_iter_value завершением.

    Таким образом, грязное решение будет использоваться

     printf("%.*s %.*s\n", (int) key_len, key_ptr, (int) value_len, value_ptr); 

    вместо

     printf("%s %s\n", key_ptr, value_ptr); 

    Однако ИМО лучше скопировать эти значения в соответствии с их длиной, а затем использовать их.

    Как вы можете видеть в https://github.com/google/leveldb/blob/master/db/c.cc#L197 leveldb_get создает срез соответствующей длины ( Slice(key, keylen) на L205) и возвращает копию ключа ( CopyString на L208).

    Дополнительно:

    Я проверил ваш код с valgrind, и есть некоторые утечки памяти с параметрами. Вы должны вручную освободить их (например, leveldb_writeoptions_destroy для woptions ). Результаты leveldb_get ( read ) также должны быть освобождены.

    Пример кода:

     // allocate new strings char * key = (char *) malloc(key_len + 1); char * value = (char *) malloc(value_len + 1); // copy string content and ensure that string is null-terminated memcpy(key, key_ptr, key_len); key[key_len] = 0; memcpy(value, value_ptr, value_len); value[value_len] = 0; // print printf("%s %s\n", key, value); // free free(key); free(value); 

    LevelDB не использует строки C (++) для ключей и значений, он использует массивы байтов, которые могут содержать NUL и не заканчиваются NUL. Это описано здесь: 1 .

    Было бы неправильно использовать любую строковую функцию C для управления этими массивами. Вы не можете использовать printf для безопасного отображения возвращаемых значений.