我在我的C应用程序中嵌入了V8。我能够在我的C应用程序中执行javascript。然而,当我试图运行我的C应用程序时,我看到了大量内存泄漏、条件跳转。我一共有4份文件。
1. mjse_int.h
typedef struct
{
std::unique_ptr<v8::Platform> platform;
v8::Isolate::CreateParams create_params;
v8::Isolate *isolate;
}MJSEInstance;2. mjse.h
#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
#endif3. mjse.c
#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
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
从功能的角度看,它看起来很好。然而,有相当多的条件跳转和内存泄漏,如下所示(只有少数几个保持较小的大小)。
==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。
char *jscript = "function js_add_elements1() \
{ \
return 10; \
};\
js_add_elements1();";使用上面的javascript,我没有看到条件内存跳转到未初始化的值。可能是什么原因?
发布于 2019-06-25 14:48:26
free(instance);释放内存,但防止unique_ptr (平台成员)破坏。尝试:
instance->~MJSEInstance();
free(instance):或者更好地使用新的和删除,而不是malloc和免费。
https://stackoverflow.com/questions/56756508
复制相似问题