首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >V8内存泄漏和条件跳转

V8内存泄漏和条件跳转
EN

Stack Overflow用户
提问于 2019-06-25 14:35:48
回答 1查看 116关注 0票数 0

我在我的C应用程序中嵌入了V8。我能够在我的C应用程序中执行javascript。然而,当我试图运行我的C应用程序时,我看到了大量内存泄漏、条件跳转。我一共有4份文件。

1. mjse_int.h

代码语言:javascript
复制
typedef struct
{
    std::unique_ptr<v8::Platform> platform;
    v8::Isolate::CreateParams create_params;
    v8::Isolate *isolate;
}MJSEInstance;

2. mjse.h

代码语言:javascript
复制
#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Create MJSE instance
*/
void *mjse_create_instance(char **argv);

/**
* @brief Destroy MJSE instance
* @param instance -> MJSE instance
*/
void mjse_destroy_instance(void *minstance);

/**
* @brief Executes a script
* @param minstance - MJSE instance
* @param script - the javascript
* @param scriptlen - Length of script
*/
void mjse_execute_script(void *minstance, char *script, int scriptlen);

#ifdef __cplusplus
}
#endif

#endif

3. mjse.c

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "include/libplatform/libplatform.h"
#include "include/v8.h"
#include "mjse.h"
#include "mjse_int.h"

extern "C"  {

using namespace v8;

void *mjse_create_instance(char **argv)
{
    MJSEInstance *instance = (MJSEInstance *)calloc(1, sizeof(MJSEInstance));

    v8::V8::InitializeICUDefaultLocation(argv[0]);
    v8::V8::InitializeExternalStartupData(argv[0]);
    instance->platform = v8::platform::NewDefaultPlatform();

    v8::V8::InitializePlatform(instance->platform.get());
    v8::V8::Initialize();

    instance->create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
    instance->isolate = v8::Isolate::New(instance->create_params);

    printf("Version: %s\n", v8::V8::GetVersion());

    return instance;
}

void mjse_destroy_instance(void *minstance)
{
    MJSEInstance *instance = (MJSEInstance *)minstance;

    if(instance == NULL)
        return;

    if(instance->isolate)
    {
        instance->isolate->Dispose();
    }

    v8::V8::Dispose();
    v8::V8::ShutdownPlatform();

    if(instance->create_params.array_buffer_allocator)
    {
        delete instance->create_params.array_buffer_allocator;
    }

    free(instance);
}

void mjse_execute_script(void *minstance, char *script, int scriptlen)
{
    MJSEInstance *instance = (MJSEInstance *)minstance;

    v8::Isolate::Scope isolate_scope(instance->isolate);

    // Create a stack-allocated handle scope.
    v8::HandleScope handle_scope(instance->isolate);

    // Create a new context.
    v8::Local<v8::Context> context = v8::Context::New(instance->isolate);

    // Enter the context for compiling and running the hello world script.
    v8::Context::Scope context_scope(context);

    {
        // Create a string containing the JavaScript source code.
        v8::Local<v8::String> source =
          v8::String::NewFromUtf8(instance->isolate, script,
          v8::NewStringType::kNormal).ToLocalChecked();

        // Compile the source code.
        v8::Local<v8::Script> script =
          v8::Script::Compile(context, source).ToLocalChecked();

        // Run the script to get the result.
        v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();

        // Convert the result to an UTF8 string and print it.
        v8::String::Utf8Value utf8(instance->isolate, result);
        printf("%s\n", *utf8);
    }
}
}

使用这3个文件,我构建了一个.so文件。现在我的测试代码如下所示。

4.主要c

代码语言:javascript
复制
int main(int argc, char **argv)
{
    int len;
    char *script;
    void *instance;

    instance = mjse_create_instance(argv);

    script =    "function js_add_elements1(var1, var2) \
                { \
                    var var3 = parseInt(var1) + parseInt(var2); \
                    var result = 'Addition of ' + var1 + ' and ' + var2 + ' results ' + var3; \
                    return result; \
                };\
                js_add_elements1(2, 3);";

    len = strlen(script);
    mjse_execute_script(instance, script, len);

    script =    "function js_add_elements2(var1, var2) \
                { \
                    var var3 = parseInt(var1) + parseInt(var2); \
                    var result = 'Addition of ' + var1 + ' and ' + var2 + ' results ' + var3; \
                    return result; \
                };\
                js_add_elements2(2, 3);";

    len = strlen(script);
    mjse_execute_script(instance, script, len);

    script =    "function js_add_elements3(var1, var2) \
                { \
                    var var3 = parseInt(var1) + parseInt(var2); \
                    var result = 'Addition of ' + var1 + ' and ' + var2 + ' results ' + var3; \
                    return result; \
                };\
                js_add_elements3(2, 3);";

    len = strlen(script);
    mjse_execute_script(instance, script, len);

    mjse_destroy_instance(instance);

    return 0;
}

用这个,我构建了main.c并进行了测试。输出如下所示。

版本: 7.7.0 (候选人) 增加2和3项结果5 增加2和3项结果5 增加2和3项结果5

从功能的角度看,它看起来很好。然而,有相当多的条件跳转和内存泄漏,如下所示(只有少数几个保持较小的大小)。

代码语言:javascript
复制
==31273== Conditional jump or move depends on uninitialised value(s)
==31273==    at 0x5DB55E8: v8::internal::DeclarationScope::CheckConflictingVarDeclarations() (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x599DCE8: v8::internal::PreParser::PreParseFunction(v8::internal::AstRawString const*, v8::internal::FunctionKind, v8::internal::FunctionLiteral::FunctionType, v8::internal::DeclarationScope*, int*, v8::internal::ProducedPreparseData**, int) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x597C6B5: v8::internal::Parser::SkipFunction(v8::internal::AstRawString const*, v8::internal::FunctionKind, v8::internal::FunctionLiteral::FunctionType, v8::internal::DeclarationScope*, int*, int*, v8::internal::ProducedPreparseData**) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x5970495: v8::internal::Parser::ParseFunctionLiteral(v8::internal::AstRawString const*, v8::internal::Scanner::Location, v8::internal::FunctionNameValidity, v8::internal::FunctionKind, int, v8::internal::FunctionLiteral::FunctionType, v8::internal::LanguageMode, v8::internal::ZoneList<v8::internal::AstRawString const*>*) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x5996C7A: v8::internal::ParserBase<v8::internal::Parser>::ParseHoistableDeclaration(int, v8::base::Flags<v8::internal::ParseFunctionFlag, int>, v8::internal::ZoneList<v8::internal::AstRawString const*>*, bool) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x596EFE6: v8::internal::Parser::DoParseProgram(v8::internal::Isolate*, v8::internal::ParseInfo*) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x596E6D8: v8::internal::Parser::ParseProgram(v8::internal::Isolate*, v8::internal::ParseInfo*) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x599A4D9: v8::internal::parsing::ParseProgram(v8::internal::ParseInfo*, v8::internal::Isolate*) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x56EF5B5: v8::internal::(anonymous namespace)::CompileToplevel(v8::internal::ParseInfo*, v8::internal::Isolate*, v8::internal::IsCompiledScope*) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x56F0EA8: v8::internal::Compiler::GetSharedFunctionInfoForScript(v8::internal::Isolate*, v8::internal::Handle<v8::internal::String>, v8::internal::Compiler::ScriptDetails const&, v8::ScriptOriginOptions, v8::Extension*, v8::internal::ScriptData*, v8::ScriptCompiler::CompileOptions, v8::ScriptCompiler::NoCacheReason, v8::internal::NativesFlag) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x56B5C64: v8::ScriptCompiler::CompileUnboundInternal(v8::Isolate*, v8::ScriptCompiler::Source*, v8::ScriptCompiler::CompileOptions, v8::ScriptCompiler::NoCacheReason) (in /usr/local/mysys/system/libs/libmjse.so)
==31273==    by 0x56B6356: v8::ScriptCompiler::Compile(v8::Local<v8::Context>, v8::ScriptCompiler::Source*, v8::ScriptCompiler::CompileOptions, v8::ScriptCompiler::NoCacheReason) (in /usr/local/mysys/system/libs/libmjse.so)
==31273== 

==31273==    LEAK SUMMARY:<br>
==31273==    definitely lost: 144 bytes in 1 blocks<br>
==31273==    indirectly lost: 1,744 bytes in 11 blocks<br>
==31273==    possibly lost: 960 bytes in 3 blocks<br>
==31273==    still reachable: 1,474 bytes in 18 blocks<br>
==31273==    suppressed: 0 bytes in 0 blocks<br>

不知道这里出了什么问题。在这方面的任何帮助,高度赞赏。

编辑

在按照Radosław Cybulski的建议修改代码之后,内存泄漏就消失了。只有仍可达的内存168个字节存在。

然而,仍然存在未初始化值的条件跳转(使用valgrind )。如果我在javascript中删除函数参数,我观察到的一件事是,这些未初始化值的条件跳转没有显示。假设我会有如下的javascript。

代码语言:javascript
复制
char *jscript =  "function js_add_elements1() \
    { \
        return 10; \
    };\

js_add_elements1();";

使用上面的javascript,我没有看到条件内存跳转到未初始化的值。可能是什么原因?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-25 14:48:26

代码语言:javascript
复制
free(instance);

释放内存,但防止unique_ptr (平台成员)破坏。尝试:

代码语言:javascript
复制
instance->~MJSEInstance();
free(instance):

或者更好地使用新的和删除,而不是malloc和免费。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56756508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档