-
Notifications
You must be signed in to change notification settings - Fork 588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Virtualizing a class causes a method returning a String return a dangling pointer #656
Comments
Does this happen only with PyTorch and only with Module? It's not possible to reproduce this with a smaller example? |
Here is one: #include <string>
class M {
std::string name = "Bob";
public:
const std::string& n() const { return name; }
}; With public native @Const @StdString @ByRef BytePointer n(); Generated JNI: JNIEXPORT jobject JNICALL Java_virtopt_M_n(JNIEnv* env, jobject obj) {
M* ptr = (M*)jlong_to_ptr(env->GetLongField(obj, JavaCPP_addressFID));
if (ptr == NULL) {
env->ThrowNew(JavaCPP_getClass(env, 9), "This pointer address is NULL.");
return 0;
}
jlong position = env->GetLongField(obj, JavaCPP_positionFID);
ptr += position;
jobject rarg = NULL;
const signed char* rptr;
jthrowable exc = NULL;
try {
StringAdapter< char > radapter(ptr->n());
rptr = radapter;
jlong rcapacity = (jlong)radapter.size;
void* rowner = radapter.owner;
void (*deallocator)(void*) = rowner != NULL ? &StringAdapter< char >::deallocate : 0;
if (rptr != NULL) {
rarg = JavaCPP_createPointer(env, 10);
if (rarg != NULL) {
JavaCPP_initPointer(env, rarg, rptr, rcapacity, rowner, deallocator);
}
}
} catch (...) {
exc = JavaCPP_handleException(env, 8);
}
if (exc != NULL) {
env->Throw(exc);
}
return rarg;
} Running a test with Without public native @StdString BytePointer n(); Generated JNI: JNIEXPORT jobject JNICALL Java_virtopt_M_n(JNIEnv* env, jobject obj) {
M* ptr = (M*)jlong_to_ptr(env->GetLongField(obj, JavaCPP_addressFID));
if (ptr == NULL) {
env->ThrowNew(JavaCPP_getClass(env, 9), "This pointer address is NULL.");
return 0;
}
jlong position = env->GetLongField(obj, JavaCPP_positionFID);
ptr += position;
jobject rarg = NULL;
signed char* rptr;
jthrowable exc = NULL;
try {
StringAdapter< char > radapter(ptr->n());
rptr = radapter;
jlong rcapacity = (jlong)radapter.size;
void* rowner = radapter.owner;
void (*deallocator)(void*) = rowner != NULL ? &StringAdapter< char >::deallocate : 0;
if (rptr != NULL) {
rarg = JavaCPP_createPointer(env, 10);
if (rarg != NULL) {
JavaCPP_initPointer(env, rarg, rptr, rcapacity, rowner, deallocator);
}
}
} catch (...) {
exc = JavaCPP_handleException(env, 8);
}
if (exc != NULL) {
env->Throw(exc);
}
return rarg;
} Test yields |
This is solved by removing the test of |
I see, what it should map to is actually something like this: public native @Cast({"", "const std::string&"}) @StdString @ByRef BytePointer n(); The logic for that is currently missing from the Parser, but we can easily work around that with Info.javaText(), unless of course there's too many of those functions, in which case it would make sense to spend time on this. When the function doesn't get virtualized though, such as in this case, we don't need to worry about that logic anyway. We can probably just change the |
What exactly is the missing logic ? What are the functions concerned ? Following your suggestion I have turned off |
Anything required to output that. I haven't looked into it, but probably declarator().
Because we need to override the function in C++ and that requires the exact same declaration to work, down to every single |
The JNI code for method
name
ofModule
in Pytorch contains:If we add an
Info
virtualize()
onModule
, the code becomes:The
const
modifier ofrptr
, when present or not, changes which overload of the implicit cast on the last line is applied. When absent, a copy of the string is performed. When present, no copy is performed and the returned pointer is dangling because the string it points to is freed at the end of the block.Probably related to #374
The text was updated successfully, but these errors were encountered: