我在我的C应用程序中嵌入了V8。我可以在C应用程序中执行javascript。但是,当我尝试运行C应用程序时,看到大量内存泄漏和条件跳转。我总共有4个文件。
typedef struct
{
std::unique_ptr<v8::Platform> platform;
v8::Isolate::CreateParams create_params;
v8::Isolate *isolate;
}MJSEInstance;
#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
#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文件。现在我的测试代码如下所示。
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ławCybulski的建议修改代码后,内存泄漏消失了。仅存在仍可访问的内存168字节。
但是仍然存在未初始化值的条件跳转(使用valgrind run)。我观察到的一件事是,如果删除javascript中的函数参数,则未显示这些针对未初始化值的条件跳转。说我将有如下所示的javascript。
char *jscript = "function js_add_elements1() \
{ \
return 10; \
};\
js_add_elements1();";
使用上述javascript,我看不到未初始化值的条件内存跳转。可能是什么原因?
答案 0 :(得分:1)
free(instance);
释放内存,但防止unique_ptr(平台成员)破坏。试试:
instance->~MJSEInstance();
free(instance):
或者甚至更好地使用new和delete代替malloc和free。