Piotr Wach software developer

Android NDK: exceptions crash on ARM 32bit when compiled with clang and c++_shared

At work we use clang and STL standard library from c++_shared included in the NDK. This week we have got nasty surprise when we were trying to run some code that was throwing an exception in our async library. This seemed to happend only on ARM 32bit devices. After a bit of digging, we have found bug report that describes more or less our situation.

We have built small test program that let us test few scenarios and that this is really a bug in STL library shipped with Android NDK:

// jni/hello.cpp
#include <stdexcept>
#include <iostream>
int main() {
  std::cerr << "1\n";
  try {
    throw std::runtime_error("A"); // crash! but only on arm 32bit, and when compiled with clang
  } catch (std::exception& e) {}
  std::cerr << "2\n";
}
## jni/Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.cpp
LOCAL_CPPFLAGS := -frtti -fexceptions -fPIE -pie
LOCAL_LDLIBS := -llog -pie
include $(BUILD_EXECUTABLE)

## jni/Application.mk
APP_STL:=c++_shared
APP_ABI:=armeabi-v7a
NDK_TOOLCHAIN_VERSION:=clang

To fix it, we had to switch from c++_shared to c++_static. However, because we had multiple shared libraries, we had to change the way we build our code, so that we don’t break ODR. Instead of building multiple shared libraries, we now build all libraries statically and link them together into one shared library.

This bug was recently fix, and should be available in the next Android NDK release (r12?).

Android NDK: Create shared library from a static library

Let’s assume you want to create one shared library from two static libraries. Here is how to do it:

In your Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE := lib1
LOCAL_SRC_FILES := lib1.cpp
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := lib2
LOCAL_SRC_FILES := lib2.cpp
include $(BUILD_STATIC_LIBRARY)

# this shared library will have all symbols from two above libraries
include $(CLEAR_VARS)
LOCAL_MODULE := lib_shared
LOCAL_SRC_FILES := empty.cpp
LOCAL_WHOLE_STATIC_LIBRARIES := lib1 lib2
include $(BUILD_SHARED_LIBRARY)

Important option to note is LOCAL_WHOLE_STATIC_LIBRARIES. If you use regular LOCAL_STATIC_LIBRARIES, because you don’t use any symbols from lib1 or lib2 in lib_shared, they will be stripped at link time. To prevent this from happening LOCAL_WHOLE_STATIC_LIBRARIES adds following options to link line to make sure symbols are not stripped:

-Wl,--whole-archive -llib1 -llib2 -Wl,--no-whole-archive

Here is documentation for --whole-archive:

--whole-archive

For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.

Game from IGK 2014

My team have just came back from IGK 2014 game developer conference. Below is a screenshot from our game, and link if you would like to play it: IGK2014

screenshot

Bug in C++ standard library: std::bind

While working on cross platform C++ library, I have found that this code crashes if compiled with Xcode 5:

#include <iostream>
#include <functional>

int main(int argc, const char * argv[])
{
    std::function<void(int)> function = [](int){};
    auto binding = std::bind(function, 10);
    // crashes here with EXC_BAD_ACCESS
    std::function<void()> jobFunctor = binding;
    return 0;
}

When converting the result of the bind to jobFunctor there is an infinite stack recursion in a std::function constructor.

clang version:

$ clang++ --version
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

Turns out there is official bug report about it: http://llvm.org/bugs/show_bug.cgi?id=18282

Above example works fine in Xcode 5.1.

UITableView controller

UITableView can cause containing it view controller to grow significantly by implementing it’s delegates UITableViewDataSource and UITableViewDelegate. UITableView controller is a solution that we come up with recently, as we were modernizing our code base to make it more modular, extensible and easier to maintain. There are several problems when view controller implements UITableView’s delegates directly:

  • view controller grows by couple of hundred lines (depending how complex are your views)
  • UITableView and it’s content is not reusable in other parts of the app
  • difficult to modify, if you want to add sections or rows that are not part of your model, but rather part of presentation layer (for example, if you want to show featured articles in the additional section or last row should shows loading… when app is loading more elements for that list)
  • if model is not compatible with UITableView (like for example hierarchy of objects that you cannot map directly to UITableViewDataSource methods) you can end up mixing view controller’s code with logic that transforms your model to something that can be displayed as a list
  • not unit testable

Instead we can implement something that I will call UITableView controller, that moves implementation of delegates to new class, and separates different responsibilities of displaying a list. Diagram below illustrates how it works: img TableController implements UITableViewDelegate and UITableViewDataSource, and delegates creating views for cells and sections to ITableViewCellFacotry and ITableViewSectionFactory,  it also reads data from ITableViewModel and ITableViewSectionModel to supply UITableView with information about number of rows and sections. This implementation is simple and works great. In my case we had several different lists that we had to display on the screen, each list was backed by different model, but they all used the same cells to display the data. We also had cases when we have to display extra cell at the end of the section or create a whole new section that does not exist in your model, but is part of your presentation. In cases like that you can build layers of ITableViewModel, where each layer performs one transformation, for example: img

BasicTableViewModel* basicModel = [[BasicTableViewModel alloc] initWithModel:model];

// notice that order in which we perform transformations make a difference:
// 1. load more in each section + additional section for featured content without load more
// 2. additional section for featured content + load more in each section
LoadMoreTableViewModel* loadMoreModel =
  [[LoadMoreTableViewModel alloc] initWithTableViewModel:basicModel ];
FeaturedTableViewModel* featuredModel =
  [[FeaturedTableViewModel alloc] initWithTableViewModel:loadMoreModel];

TableController *tableController = [[TableController alloc] init];
tableController.model = featuredModel;