Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么主题行会出现分段错误_C++_Node.js_Segmentation Fault_Rocksdb_Node Native Addon - Fatal编程技术网

C++ 为什么主题行会出现分段错误

C++ 为什么主题行会出现分段错误,c++,node.js,segmentation-fault,rocksdb,node-native-addon,C++,Node.js,Segmentation Fault,Rocksdb,Node Native Addon,我正在为RocksDB创建一个本机节点扩展,我已经解决了一个无法解释的问题。因此,我有以下功能完善的代码: std::string v; ROCKSDB_STATUS_THROWS(db->Get(*options, k, &v)); napi_value result; NAPI_STATUS_THROWS(napi_create_buffer_copy(env, v.size(), v.c_str(), nullptr, &result)); return resu

我正在为RocksDB创建一个本机节点扩展,我已经解决了一个无法解释的问题。因此,我有以下功能完善的代码:

std::string v;

ROCKSDB_STATUS_THROWS(db->Get(*options, k, &v));

napi_value result;
NAPI_STATUS_THROWS(napi_create_buffer_copy(env, v.size(), v.c_str(), nullptr, &result));
return result;
但是,当我引入一个优化,减少了一个额外的
memcpy
时,我得到了一个错误:

std::string *v = new std::string();

ROCKSDB_STATUS_THROWS(db->Get(*options, k, v)); // <============= I get segfaults here

napi_value result;
NAPI_STATUS_THROWS(napi_create_external_buffer(env, v->size(), (void *)v->c_str(), rocksdb_get_finalize, v, &result));
return result;
有没有想过为什么会发生这种情况

提前谢谢你

编辑

为了确定,我还检查了以下版本(它也失败):

编辑

根据评论中的要求,提供更完整的示例:

#include <napi-macros.h>
#include <node_api.h>

#include <rocksdb/db.h>
#include <rocksdb/convenience.h>
#include <rocksdb/write_batch.h>
#include <rocksdb/cache.h>
#include <rocksdb/filter_policy.h>
#include <rocksdb/cache.h>
#include <rocksdb/comparator.h>
#include <rocksdb/env.h>
#include <rocksdb/options.h>
#include <rocksdb/table.h>

#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

...

/**
 * Runs when a rocksdb_get return value instance is garbage collected.
 */
static void rocksdb_get_finalize(napi_env env, void *data, void *hint)
{
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get_finalize (started)";
    if (hint)
    {
        LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get_finalize (finished)";
        delete (std::string *)hint;
    }
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get_finalize (finished)";
}

/**
 * Gets key / value pair from a database.
 */
NAPI_METHOD(rocksdb_get)
{
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (started)";

    NAPI_ARGV(3);

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting db argument)";
    rocksdb::DB *DECLARE_FROM_EXTERNAL_ARGUMENT(0, db);
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting k argument)";
    DECLARE_SLICE_FROM_BUFFER_ARGUMENT(1, k);
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting options argument)";
    rocksdb::ReadOptions *DECLARE_FROM_EXTERNAL_ARGUMENT(2, options);

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (declaring v variable)";
    std::string *v = new std::string();

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting value from database)";
    ROCKSDB_STATUS_THROWS(db->Get(*options, k, v));

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (wrapping value with js wrapper)";
    napi_value result;
    NAPI_STATUS_THROWS(napi_create_external_buffer(env, v->size(), (void *)v->c_str(), rocksdb_get_finalize, v, &result));
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (finished)";
    return result;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“easylogging++.h”
初始化_EASYLOGGINGPP
...
/**
*当rocksdb_get返回值实例被垃圾回收时运行。
*/
静态void rocksdb_get_finalize(napi_env env,void*数据,void*提示)
{
日志(如果已启用日志,信息)
但当我引入一个优化,减少了一个额外的内存

不清楚您认为自己在优化哪些额外的
memcpy

如果字符串很短,并且您正在使用
std::string
进行短字符串优化,那么实际上您将优化出一个短
memcpy
。然而,动态分配然后删除
std::string
可能比
memcpy
要昂贵得多

如果字符串很长,您实际上根本不会优化任何内容,而是无缘无故地使代码变慢

我发现:

std::string *v = new std::string();

ROCKSDB_STATUS_THROWS(db->Get(*options, k, v)); // <============= I get segfaults here

napi_value result;
NAPI_STATUS_THROWS(napi_create_external_buffer(env, v->size(), (void *)v->c_str(), rocksdb_get_finalize, v, &result));
return result;

添加
v=new std::string;…;delete v;
引入了
SIGSEGV
这一事实很可能表明您正在发生一些其他堆损坏,直到您稍微改变了一些东西之后才会被注意到。这是您的朋友。

您能澄清一下,对于最小的可复制示例,违反了哪些语句吗根据我的理解,ovided示例已经是一个最小且可复制的示例,我可以推动整个项目(两个项目)到GitHub并提供链接,但这不是最小的,也不可能提供一个没有项目所有依赖项的工作代码示例,这再次违反了最小值…@Lu4•如果我可以将您的代码复制粘贴到我自己的foo.cpp文件中,然后编译并运行它,那就太好了。您不需要包含任何依赖项,但一个完整的示例将包含一个主方法和您使用的includes。好的,我已经更新了答案,我真的希望它有帮助,但我看到它引入了许多不必要的上下文,可能会使事情难以使用……好的,我实际上注意到还有另一个API支持更智能的内存管理,满足我的需要理想情况下:,无论如何,谢谢你!
#include <napi-macros.h>
#include <node_api.h>

#include <rocksdb/db.h>
#include <rocksdb/convenience.h>
#include <rocksdb/write_batch.h>
#include <rocksdb/cache.h>
#include <rocksdb/filter_policy.h>
#include <rocksdb/cache.h>
#include <rocksdb/comparator.h>
#include <rocksdb/env.h>
#include <rocksdb/options.h>
#include <rocksdb/table.h>

#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

...

/**
 * Runs when a rocksdb_get return value instance is garbage collected.
 */
static void rocksdb_get_finalize(napi_env env, void *data, void *hint)
{
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get_finalize (started)";
    if (hint)
    {
        LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get_finalize (finished)";
        delete (std::string *)hint;
    }
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get_finalize (finished)";
}

/**
 * Gets key / value pair from a database.
 */
NAPI_METHOD(rocksdb_get)
{
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (started)";

    NAPI_ARGV(3);

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting db argument)";
    rocksdb::DB *DECLARE_FROM_EXTERNAL_ARGUMENT(0, db);
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting k argument)";
    DECLARE_SLICE_FROM_BUFFER_ARGUMENT(1, k);
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting options argument)";
    rocksdb::ReadOptions *DECLARE_FROM_EXTERNAL_ARGUMENT(2, options);

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (declaring v variable)";
    std::string *v = new std::string();

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (getting value from database)";
    ROCKSDB_STATUS_THROWS(db->Get(*options, k, v));

    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (wrapping value with js wrapper)";
    napi_value result;
    NAPI_STATUS_THROWS(napi_create_external_buffer(env, v->size(), (void *)v->c_str(), rocksdb_get_finalize, v, &result));
    LOG_IF(logging_enabled, INFO) << LOCATION << " rocksdb_get (finished)";
    return result;
}
import path from 'path';
import { bindings as rocks, Unique, BatchContext } from 'rocksdb';

import { MapOf } from '../types';
import { Command, CommandOptions, CommandOptionDeclaration, Persist, CommandEnvironment } from '../command';

// tslint:disable-next-line: no-empty-interface
export interface PullCommandOptions {
}

@Command
export class ExampleCommandNameCommand implements Command {
    public get description(): string {
        return "[An example command description]";
    }

    public get options(): CommandOptions<CommandOptionDeclaration> {
        const result: MapOf<PullCommandOptions, CommandOptionDeclaration> = new Map();

        return result;
    }

    public async run(environment: CommandEnvironment, opts: CommandOptions<unknown>): Promise<void> {
        // let options = opts as unknown as PullCommandOptions;

        let window = global as any;

        window.rocks = rocks;

        const configPath = path.resolve('log.conf');
        const configPathBuffer = Buffer.from(configPath);

        rocks.logger_config(configPathBuffer);
        rocks.logger_start();

        let db = window.db = rocks.rocksdb_open(Buffer.from('test.db', 'utf-8'), rocks.rocksdb_options_init());
        let readOptions = window.readOptions = rocks.rocksdb_read_options_init();
        let writeOptions = window.writeOptions = rocks.rocksdb_write_options_init();

        // ===== The line below launches the C++ method
        rocks.rocksdb_put(db, Buffer.from('Zookie'), Buffer.from('Cookie'), writeOptions);
        // ===== The line above launches the C++ method

        console.log(rocks.rocksdb_get(db, Buffer.from('Zookie'), readOptions).toString());

        let batch: Unique<BatchContext> | null = rocks.rocksdb_batch_init();

        rocks.rocksdb_batch_put(batch, Buffer.from('Cookie'), Buffer.from('Zookie'));
        rocks.rocksdb_batch_put(batch, Buffer.from('Pookie'), Buffer.from('Zookie'));
        rocks.rocksdb_batch_put(batch, Buffer.from('Zookie'), Buffer.from('Zookie'));
        rocks.rocksdb_batch_put(batch, Buffer.from('Hookie'), Buffer.from('Zookie'));
        await rocks.rocksdb_batch_write_async(db, batch, writeOptions);

        batch = null;

        let proceed = true;

        while (proceed) {
            await new Promise(resolve => setTimeout(resolve, 1000));
        }
    }
}