Electron app crashes when using freepointer
ffi-rs version 1.2.5
Print current Node.js info with the following code
ffi-rs/package.json:
{
"name": "ffi-rs",
"version": "1.2.5",
"main": "index.js",
"types": "index.d.ts",
"description": "A module written in Rust and N-API provides interface (FFI) features for Node.js",
"napi": {
"name": "ffi-rs",
"triples": {
"additional": [
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"arm-unknown-linux-gnueabihf",
"i686-pc-windows-msvc",
"x86_64-unknown-linux-musl",
"aarch64-pc-windows-msvc"
]
}
},
"author": "zhangyuang",
"homepage": "https://github.com/zhangyuang/node-ffi-rs#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/zhangyuang/node-ffi-rs.git"
},
"keywords": [
"ffi",
"rust",
"node.js",
"napi"
],
"files": [
"index.js",
"index.d.ts",
"README.md"
],
"license": "MIT",
"dependencies": {},
"devDependencies": {
"@napi-rs/cli": "^2.15.2",
"@types/node": "^20.8.7",
"benny": "^3.7.1",
"conventional-changelog-cli": "^4.1.0",
"esno": "^4.0.0",
"ffi-napi": "^4.0.3",
"koa": "^2.14.2",
"shelljs": "^0.8.5",
"typescript": "^5.4.5"
},
"scripts": {
"artifacts": "napi artifacts",
"build:c": "node scripts/compile.js",
"build:dev": "env=development node scripts/build.js",
"build": "node scripts/build.js",
"publish:npm": "node scripts/publish.js",
"test": "esno ./tests/index.ts",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add . && git commit -m \"docs: update changelog.md\" && git push origin master",
"pub": "npm version patch && git push origin master --tags && npm run changelog",
"pub:alpha": "npm version prerelease --preid=alpha && git push origin master --tags"
},
"optionalDependencies": {
"@yuuang/ffi-rs-darwin-arm64": "1.2.5",
"@yuuang/ffi-rs-darwin-x64": "1.2.5",
"@yuuang/ffi-rs-linux-arm-gnueabihf": "1.2.5",
"@yuuang/ffi-rs-linux-arm64-gnu": "1.2.5",
"@yuuang/ffi-rs-linux-arm64-musl": "1.2.5",
"@yuuang/ffi-rs-linux-x64-gnu": "1.2.5",
"@yuuang/ffi-rs-linux-x64-musl": "1.2.5",
"@yuuang/ffi-rs-win32-arm64-msvc": "1.2.5",
"@yuuang/ffi-rs-win32-ia32-msvc": "1.2.5",
"@yuuang/ffi-rs-win32-x64-msvc": "1.2.5"
}
}
$ ls node_modules/@yuuang
ffi-rs-win32-ia32-msvc/ ffi-rs-win32-x64-msvc/
Current Node.js arch
x64 win32
Descibe your problem in detail
I am trying out the example for passing function pointers to C functions. I slightly altered the example so that the funcExternal function pointer gets freed when the C++ code is done with it. This is done by setting a callback function that frees the function pointer.
typedef void (*CleanupFunctionPointer)();
CleanupFunctionPointer cleanupFunction = nullptr;
extern "C" void setCleanupFunction(CleanupFunctionPointer cleanup) {
cleanupFunction = cleanup;
}
typedef const void (*FunctionPointer)(int a, bool b, char *c, double d,
char **e, int *f);
extern "C" void callFunction(FunctionPointer func) {
for (int i = 0; i < 2; i++) {
int a = 100;
... left out for brevity ....
func(a, b, c, d, stringArray, i32Array);
free(c);
free(stringArray[0]);
free(stringArray[1]);
free(stringArray);
free(i32Array);
}
if (cleanupFunction != nullptr) {
cleanupFunction();
cleanupFunction = nullptr;
}
}
The following javascript code sets the callback in C++.
const cleanupFunction = () => {
console.log("C++ is done, freeing function pointer.");
// free function memory when it is not in use
setTimeout(() => {
freePointer({
paramsType: [funcConstructor({
paramsType: [
DataType.I32,
DataType.Boolean,
DataType.String,
DataType.Double,
arrayConstructor({
type: DataType.StringArray,
length: 2
}),
arrayConstructor({
type: DataType.I32Array,
length: 3
}),
],
retType: DataType.Void,
})],
paramsValue: funcExternal,
pointerType: PointerType.CPointer
})
}, 1000);
}
const cleanupPointer = createPointer({
paramsType: [funcConstructor({
paramsType: [],
retType: DataType.Void,
})],
paramsValue: [cleanupFunction]
})
load({
library: "libsum",
funcName: "setCleanupFunction",
retType: DataType.Void,
paramsType: [
DataType.External,
],
paramsValue: unwrapPointer(cleanupPointer),
})
Result
a: 100
b: false
c: Hello, World!
d: 100.11
e: [ 'Hello', 'world' ]
f: [ 101, 202, 303 ]
a: 100
b: false
c: Hello, World!
d: 100.11
e: [ 'Hello', 'world' ]
f: [ 101, 202, 303 ]
C++ is done, freeing function pointer.
The JS function is called twice from within the 'callFunction' in C++, after which the JS function pointer(funcExternal) should get freed with the cleanupFunction callback.
This results in crashing the process.
Remarks
This does not happen when using PointerType.RsPointer for pointerType field in freePointer object.
What's your expected result
freeing the funcExternal pointer in JS without crashing process.
Why do you call CleanupFunction in c? If you want to free function memory, you can call the freePointer method in Node.js directly
How can we know that C is done with the functionpointer?
In the code example for Function, the functionpointer is freed after 'func' is called from within the C function. But In the C function we call the function 'func' twice, so it's freed before C is done using it.
At least if I'm understanding correctly..
thx in advance for your guidance!
You dont need to know when the function is end,the function pointer memory only occupy some memory without any side effect.If you want to free function memory in c,you can store the function pointer in c directly and free it no need to call freePointer in Node.js
发自我的iPhone
------------------ Original ------------------ From: Japerre @.> Date: Fri,Feb 21,2025 8:32 PM To: zhangyuang/node-ffi-rs @.> Cc: yuuang @.>, Comment @.> Subject: Re: [zhangyuang/node-ffi-rs] Electron app crashes when usingfreepointer (Issue #96)
How can we know that C is done with the functionpointer?
In the code example for Function, the functionpointer is freed after 'func' is called from within the C function. But In the C function we call the function 'func' twice, so it's freed before C is done using it.
At least if I'm understanding correctly..
thx in advance for your guidance!
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***> Japerre left a comment (zhangyuang/node-ffi-rs#96)
How can we know that C is done with the functionpointer?
In the code example for Function, the functionpointer is freed after 'func' is called from within the C function. But In the C function we call the function 'func' twice, so it's freed before C is done using it.
At least if I'm understanding correctly..
thx in advance for your guidance!
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>