Segmentation fault in v8 hello world when using TryCatch - c++

I am trying to use v8 in my C++ application. I am stuck on the helloworld itself!
The helloworld at https://developers.google.com/v8/get_started works just fine. Now I am trying to catch exceptions/error in the code. So I used TryCatch trycatch;.
int main(int argc, char *argv[]) {
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
TryCatch trycatch; /* TO CATCH EXCETIONS/ERRORS */
Handle<String> source = String::New("xyz();");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();
if (result.IsEmpty()) {
fprintf(stderr, "Exception: %s\n",
*String::AsciiValue(trycatch.Exception()));
return -1;
}
String::AsciiValue ascii(result);
printf("%s\n", *ascii);
context.Dispose();
return 0;
}
The exceptions are caught fine but the program does not terminate properly. It generates a segmentation fault. What am I doing wrong?

Turned out to be a foolish thing. I had long back installed libv8-dev and forgotten about it. And now I installed V8 from source. So I had two versions of V8 on my system. I uninstalled libv8-dev and the problem has been solved.

Related

v8 example script breaks when refactoring

the following snippet is the hello-world.cc example script from the v8 embedding guide with a few minor tweaks. I can confirm that it compiles and produces the expected result.
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include "include/libplatform/libplatform.h"
#include "include/v8.h"
int main(int argc, char* argv[]) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);`
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, "'Hello' + ', World!'", v8::NewStringType::kNormal).ToLocalChecked();
v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
v8::String::Utf8Value utf8(isolate, result);
std::cout << *utf8 << std::endl;
}
isolate->Dispose();
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
delete create_params.array_buffer_allocator;
return 0;
}
I wanted to refactor this script such that the initialisation is repeatable, as I will be needing multiple isolates. I also wanted to separate the execution of the code. I refactored the script to look like this:
#include <iostream>
#include "include/libplatform/libplatform.h"
#include "include/v8.h"
v8::Local<v8::Value> execute(v8::Isolate* isolate, const char* input) {
v8::HandleScope handle_scope(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, input).ToLocalChecked();
v8::Local<v8::Script> src = v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = src->Run(context).ToLocalChecked();
return result;
}
v8::Isolate* init(std::string data) {
v8::V8::InitializeICUDefaultLocation(data.c_str());
v8::V8::InitializeExternalStartupData(data.c_str());
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
return isolate;
}
int main(int args, char* argv[]) {
v8::Isolate* isolate = init(argv[0]);
auto input = "1 + 2";
auto result = execute(isolate, input);
v8::String::Utf8Value utf8(isolate, result);
std::cout << *utf8 << std::endl;
return 0;
}
The program compiles flawlessly, except produces a segfault when run. The reason for this is baffling to me. In the example script, the execution code is placed in its own scope, and fails without it. My thinking therefore is that a function should have the same effect, however moving either pieces of code into different functions also causes the program to fail.
I've also had the honour of noticing that by moving the creation of the Context
v8::HandleScope handle_scope(isolate);
v8::Isolate::Scope isolate_scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
outside of the execute function causes the program to fail with the following message:
#
# Fatal error in v8::HandleScope::CreateHandle()
# Cannot create a handle without a HandleScope
#
I've seen many threads about this, all of which are answered by upgrading the NodeJS version, or using different functions to do the same thing. Unfortunately, this isn't applicable here, as I'm not using NodeJS.
I would also like to clarify that I'm not particularly eloquent with C/C++, so do excuse any noobishness.
I'm simply hoping for some pointers, and to explain why/how this code breaks, and what is needed to fix it.
Thanks
All v8::Locals that you create while a given HandleScope is active will become invalid when that HandleScope goes out of scope. To return a v8::Local from a function that sets up (and destroys) its own HandleScope, use an EscapableHandleScope. More details: https://v8.dev/docs/embed (search for "HandleScope").

Segmentation fault occurs when PyRun_SimpleFile is called repeatedly

I want to embed a python code written in version 3.5 in c++. Also, the python script needs to be executed as the whole script repeatedly. My code as follows. It executes well for the first iteration and gives a segmentation fault at the second iteration.
main.cpp:
#include <Python.h>
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{
int i = 0;
while(i<3){
cout<<"start"<<endl;
Py_Initialize();
FILE* file;
wchar_t* _argv[argc];
for(int i=0; i<argc; i++){
wchar_t *arg = Py_DecodeLocale(argv[i], NULL);
_argv[i] = arg;
}
PySys_SetArgv(argc, _argv);
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
PyList_Append(path, PyUnicode_FromString("."));
file = fopen("./example.py","r");
PyRun_SimpleFile(file, "./example.py");
fclose(file);
Py_Finalize();
cout<<"Done"<<endl;
i++;
}
return 0;
}
example.py:
import tensorflow as tf
flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_float('learning_rate', 0.01, 'initial learning rate')
def main(argv=None):
print(FLAGS.learning_rate)
if __name__ == '__main__':
main()
I build the project using:
cmake --build . --target Demo -- -j 2
and executed as:
./Demo --learning_rate 0.02
The output was:
start
0.02
Done
start
Segmentation fault (core dumped)
Then I replaced the content of "example.py" as:
print("Hi")
The output was:
start
Hi
Done
start
Hi
Done
start
Hi
Done
How can I fix the above mentioned segmentation fault ?
See the docs
Some extensions may not work properly if their initialization routine is called more than once; this can happen if an application calls Py_Initialize() and Py_Finalize() more than once.

error while loading shared libraries: jvm.dll

I am trying to run a java program using c++ code. I tried below code
#include<jni.h>
#include<stdio.h>
int main(int argc, char** argv) {
JavaVM* vm;
JNIEnv* env;
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 0;
vm_args.ignoreUnrecognized = 1;
// Construct a VM
jint results = JNI_CreateJavaVM(&vm, (void**)& env, &vm_args);
// Construct a String
jstring jstr = env->NewStringUTF("Hello World");
// First get the class that contains the method you need to call
jclass clazz = env->FindClass("java/lang/String");
// Get the method that you want to call
jmethodID to_lower = env->GetMethodID(clazz, "toLowerCase",
"()Ljava/lang/String;");
// Call the method on the object
jobject result = env->CallObjectMethod(jstr, to_lower);
// Get a C-style string
const char* str = env->GetStringUTFChars((jstring)result, NULL);
printf("%s\n", str);
// Clean up
env->ReleaseStringUTFChars(jstr, str);
// Shutdown the VM.
vm->DestroyJavaVM();
}
I used below command to compile the code
g++ LoadJVM.c -I/c/apps64/Java/jdk-11.0.1/include -I/c/apps64/Java/jdk-11.0.1/include/win32 -L/c/apps64/Java/jdk-11.0.1/lib/ -ljvm
It compiles fine, but when i run the executable like below, i am facing error
./a.exe
Error
error while loading shared libraries: jvm.dll: cannot open shared object file: No such file or directory
Any Idea why this jvm.dll is not getting loaded?
PS: I am compiling and running from Git-Bash on windows 10.
It looks like your jvm.dll can not be found.
Let's say we have 32bit MinGW installation (this is the version I have).
simple.cc
#include<jni.h>
#include<stdio.h>
int main(int argc, char** argv) {
JavaVM* vm;
JNIEnv* env;
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 0;
vm_args.ignoreUnrecognized = 1;
// Construct a VM
jint results = JNI_CreateJavaVM(&vm, (void**)& env, &vm_args);
printf("Hello");
// Shutdown the VM.
(*vm).DestroyJavaVM();
}
compilation and execution
> export JAVA_HOME="/c/Program\ Files\ \(x86\)/Java/jdk1.8.0_211/"
> export PATH="/c/Program Files (x86)/Java/jdk1.8.0_211/jre/bin/server/":"$PATH"
> g++ -o simple simple.cc -I"$JAVA_HOME/include/" -I"$JAVA_HOME/include/win32/" -L"$JAVA_HOME/lib" -ljvm
> ./simple
Hello
you have to make sure that jvm.dll is visible on %PATH% - $PATH inside git-bash.

C's Python API: Calling python function 2X causes Access violation writing location

I'm trying to write some C code that calls some python code to do some data analysis, and I came upon a weird issue. If I call initialize python, call a function, finalize python, and then repeat the same 1 time, I get an access violation writing location error the second time I try to call the function. The following simple code:
#include "stdafx.h"
#include <iostream>
#include "Python.h"
int main()
{
for (int testInc = 0; testInc < 2; testInc++)
{
std::cout << testInc + 1 << std::endl;
PyObject *pName, *pModule, *pFunc, *pValue;
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\"PathToCode\")");
pName = PyUnicode_DecodeFSDefault("MyModuleName");
pModule = PyImport_Import(pName);
pFunc = PyObject_GetAttrString(pModule, "MyFunctionName");
pValue = PyObject_CallObject(pFunc, NULL);
printf("Result: %s\n", PyBytes_AS_STRING(PyUnicode_AsEncodedString(pValue, "ASCII", "strict")));
Py_DECREF(pName);
Py_DECREF(pModule);
Py_DECREF(pFunc);
Py_DECREF(pValue);
Py_Finalize();
}
return 0;
}
(checks on Py_Object*'s being == NULL omitted for brevity, but they all pass). With the python code being:
def myFunctionName():
import numpy
return "Hi!"
consistently throws the error "Unhandled exception at 0x00007FFE1EBC199C (multiarray.cp35-win_amd64.pyd) in TestApplication.exe: 0xC0000005: Access violation writing location 0x000000000000000A." on the second pass through the for loop, and I'm struggling to figure out why. If I place the initialize and finalize commands outside of the for loop, then this works fine, but my understanding of these commands leads me to believe that this code should be functional. Also, if I omit the "import" command in the python script, my C code also runs fine then, leading me to believe that something weird is happening with the import. Am I misunderstanding something?

V8 - C++ binding : How to return v8 compiled script from c++ function and Run it in other function

I am currently working on ubuntu 12.04 . I have simple hello world program in c++ with v8 binding as follows :
#include "include/v8.h"
#include "include/libplatform/libplatform.h"
using namespace v8;
int main(int argc, char* argv[]) {
// Initialize V8.
V8::InitializeICU();
Platform* platform = platform::CreateDefaultPlatform();
V8::InitializePlatform(platform);
V8::Initialize();
// Create a new Isolate and make it the current one.
//Isolate* isolate = Isolate::GetCurrent();
Isolate* isolate = Isolate::New();
{
Isolate::Scope isolate_scope(isolate);
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
// Create a new context.
Local<Context> context = Context::New(isolate);
// Enter the context for compiling and running the hello world script.
Context::Scope context_scope(context);
// Create a string containing the JavaScript source code.
Local<String> source = String::NewFromUtf8(isolate, "'Hello' + ', World!'");
// Compile the source code.
Local<Script> script = Script::Compile(source);
// Run the script to get the result.
Local<Value> result = script->Run();
// Convert the result to an UTF8 string and print it.
String::Utf8Value utf8(result);
printf("%s\n", *utf8);
}
// Dispose the isolate and tear down V8.
isolate->Dispose();
V8::Dispose();
V8::ShutdownPlatform();
delete platform;
return 0;
}
I just want
compilation( Local<Script> script = Script::Compile(source);)
and
execution(Local<Value> result = script->Run();)
in different functions. Is it possible? if yes , how? Can anybody help