web-dev-qa-db-fra.com

NewStringUTF () et libération de mémoire

Dois-je libérer la chaîne allouée après l'avoir passée à NewStringUTF()?

J'ai un code similaire à:

char* test;
jstring j_test;

test = some_function(); // <- malloc()s the memory
j_test = (*env)->NewStringUTF(env, test);

free(test); // <- should this be here?

Lorsque je libère la chaîne après l'avoir passée à NewStringUTF(), j'obtiens une erreur signal 11 (SIGSEGV), fault addr deadbaad. Si je supprime l'appel free(), l'erreur disparaît. Qu'est-ce que je fais mal?

Je vois des opinions contradictoires. Certains disent que je devrais le libérer moi-même, certains disent que le VM le libère, certains disent que le VM ne le libère pas et vous devriez faire une étrange magie vaudou pour libérez-le. Je suis confus.

38
rid

Le stockage de l'argument const char* Dans NewStringUTF() est entièrement de votre responsabilité: si vous avez alloué test avec malloc(), alors vous devez free() il. Ainsi, l'extrait que vous avez publié est correct. Vous corrompez le tas ailleurs.

Je vois des opinions contradictoires. Certains disent que je devrais le libérer moi-même, certains disent que le VM le libère, certains disent que le VM ne le libère pas et vous devriez faire une étrange magie vaudou pour libérez-le. Je suis confus.

Ils parlent de l'instance jstring retournée par NewStringUTF(). Cela suit les règles déroutantes pour 'références locales' .

Ce n'est jamais une erreur de libérer cette référence avec DeleteLocalRef() lorsque vous en avez terminé. Cependant, la JVM effectue une magie douteuse si vous appelez NewStringUTF() dans le contexte d'un thread JVM. Lorsque la méthode native revient à Java, toutes les références locales perdues sont automatiquement nettoyées. Donc, si vous êtes sûr que votre appelant ultime se trouve dans un thread Java, vous pouvez alors divulguer la référence en toute sécurité.

D'un autre côté, si vous exécutez dans le contexte d'un thread natif - par exemple, certains threads de rapport d'événements effectuant des rappels à Java - il n'y a jamais de retour à Java, vous devez donc appeler DeleteLocalRef() vous-même sur ce jstring (et en effet toutes les autres références locales renvoyées par des appels JNI typiques).

70
fizzer

Vous avez juste besoin de DeleteLocalRef (), NewStringUTF () est juste de la mémoire malloc sur JVM, que la JVM prendra soin de la mémoire.

5
jsding