Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing global variables to zero on Android NDK

I'm developing an app using plain C and the latest Android NDK. I noticed that the *.so is never flushed from memory and so the global variables retain their values from the last run of the app, e.g. consider the following code:

static int init = 0;

void android_main(struct android_app* state)
{
  init = 1;
  dostuff();
}

When my app is launched for the first time, "init" is 0 and set to 1. Starting with the second run, "init" will always be 1 because the *.so is still in memory. But I want the globals to be reset to their default value whenever android_main() is called!

So is there any way to ensure that the globals are always reset before android_main() is called or do I have to do this manually? (which would be a huge work for my app because I'm having tons of globals spread across different *.c sources)

Thanks!

like image 236
andy Avatar asked Jun 16 '11 16:06

andy


2 Answers

You are kinda between a rock and a hard place. The rock being that initialized global data in shared libraries is never actually "initialized", per se. The initial values are actually in the .so file itself in DATA sections which just get copied into memory on load and Voila! initialized data.

The hard place is is that Java JNI by design has no UnloadLibrary(), and specifies that a call to LoadLibrary() for an already-loaded library is to be ignored.

This is further complicated because you are using the Android NativeActivity helper, which hides you from any of the Java that actually loads the library, as well as the Activity code itself, where you might (might) be able to end the activity when your native code is done.

I'm not sure dumping NativeActivity and just writing a thin JNI shim would help much, though, since you still wouldn't be able to unload, or reload, the native code anyway, and explicitly ending an activity in Android can be a little tricky. Actually, I'll bet you COULD get the activity to end cleanly and reliably - it's not something I do and so I am not very familiar with it.

Another possibility would be to build 2 native libraries. One would just be your app, and would have no Android-specific code in it at all. The other library would be the one loaded by NativeActivity - with android_main() and all - and it would use the dlopen() / dlsym() / dlclose() C API to load, run, and cleanup the "app" library.

I think it could work - but I've never tried it. The header to do the shared library stuff (dlfcn.h) is in the NDK.

like image 190
jimkberry Avatar answered Sep 29 '22 01:09

jimkberry


The only solution I've found is to call exit() within the native c code - However, this does have the side affect of also closing the activity. Would be interested to know if you found a better solution?

like image 33
App8ite Avatar answered Sep 29 '22 01:09

App8ite