views:

386

answers:

2

So i have this C++ program that is called via JNI from my Java program, the code follows:

    JNIEXPORT jstring JNICALL Java_com_entrust_adminservices_urs_examples_authn_LdapAuthenticator2_takeInfo(JNIEnv *env, jobject obj, jstring domain, jstring id, jstring idca, jstring password) 
{
    const char *nt_domain;
    const char *nt_id;
    const char *nt_password;
    HANDLE hToken = 0;

    bool aut = false;

    nt_domain = env->GetStringUTFChars(domain, NULL);
    nt_id = env->GetStringUTFChars(id, NULL);
    nt_password = env->GetStringUTFChars(password, NULL);

      aut = LogonUser(nt_id, nt_domain, nt_password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken );

      /* release buffers */
    env->ReleaseStringUTFChars(domain, nt_domain);
    env->ReleaseStringUTFChars(id, nt_id);
    env->ReleaseStringUTFChars(password, nt_password);
    /* release the login handle */
    CloseHandle(hToken);

    if(aut)
    {
     return env->NewStringUTF("true"); 
    }

    DWORD dwError = GetLastError();
      LPVOID lpMsgBuf;

      FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR) &lpMsgBuf, 0, NULL );

    return env->NewStringUTF((const char*)lpMsgBuf); //returns the contents of lpMsgBuf (error)
}

in that second to last line jstring newString = env->NewStringUTF((const char*)otherString); is never released, but returned, will it cause an eventual memory leak? is there anyway to get around this?

Also is it possible that instead of returning a string i return a boolean (as returned by the LogonUser function), instead of a jstring, and instead add an "errormessage" refrence to be passed in the method, and update that? will my Java program be able to see an update to "errormessage"?

Thanks.

+1  A: 

NewStringUTF() creates a new java.lang.String -- in other words, an object on the Java heap, which will get collected when there are no more references to it.

Or are you asking about otherString? I don't know what FormatMessage does, but it looks like it's allocating memory on the C heap. If that's the case, then yes, you have to explicitly free that memory.

You make your life harder by sometimes setting otherString to a constant string. Don't do that. Instead, call NewStringUTF() within the blocks of your if/else, and in the second case free the native C string.

kdgregory
thanks for the tips, i updated the code if you could have a look and see if you spot any obvious errors (im a java guy workin in a c++ world right now)
Petey B
You still don't seem to be freeing lpMsgBuf. Perhaps you don't have to; I don't know whether the FormatMessage() method allocates memory or not.
kdgregory
thanks kdgregory, as i understand it lpMsgBuf does not need to be freed, but that's neither here nore there if the rest is correct, thanks again
Petey B
Actually it does: see the documentation at http://msdn.microsoft.com/en-us/library/ms679351%28VS.85%29.aspx regarding FORMAT_MESSAGE_ALLOCATE_BUFFER
kdgregory
A: 

You don't have to worry about the memory allocated by NewStringUTF as that will be taken care of by the Java garbage collector.

But you have to free the lpMsgBuf as you are passing FORMAT_MESSAGE_ALLOCATE_BUFFER to FormatMessage (i.e. you have to use LocalFree to free that buffer), see the FormatMessage documentation.

cmeerw