我正在尝试使用c ++ 11支持为android构建boost_1.60.0(作为共享库).我正在使用最新的ndk(目前是android-ndk-r10e).构建主机是Windows-10.
这适用于非开源项目.所以据我所知,我不能使用gnustl_shared,我需要使用c ++ _ shared作为android c ++运行时.
我的project-config.jam看起来像这样:
androidNDKRoot = c:/android-ndk-r10e ;
using gcc : android :
$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ :
<root>$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/
<compileflags>-MMD
<compileflags>-MP
<compileflags>-MF
<compileflags>-fpic
<compileflags>-ffunction-sections
<compileflags>-funwind-tables
<compileflags>-fstack-protector
<compileflags>-no-canonical-prefixes
<compileflags>-march=armv5te
<compileflags>-mtune=xscale
<compileflags>-msoft-float
<compileflags>-fno-rtti
<compileflags>-mthumb
<compileflags>-Os
<compileflags>-g
<compileflags>-DNDEBUG
<compileflags>-fomit-frame-pointer
<compileflags>-fno-strict-aliasing
<compileflags>-finline-limit=64
<compileflags>-IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/libcxx/include
<compileflags>-IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/../llvm-libc++abi/libcxxabi/include
<compileflags>-IC:/android-ndk-r10e/sources/cxx-stl/llvm-libc++/../../android/support/include
<compileflags>-IC:/android-ndk-r10e/platforms/android-9/arch-arm/usr/include
<compileflags>-Wa,--noexecstack
<compileflags>-Wformat
<compileflags>-Werror=format-security
<compileflags>-DUNIX
<compileflags>-DANDROID
<compileflags>-Wl,--no-undefined
<cxxflags>-fexceptions
<linkflags>-lc++_shared
<archiver>$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-ar
<ranlib>$(androidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-ranlib
;
Run Code Online (Sandbox Code Playgroud)
build命令是:
b2 --toolset=gcc-android cxxflags="-std=c++11 " --prefix=..\boost_android_arm --builddir=./boost_android_arm/builddir target-os=linux --with-filesystem define=BOOST_FILESYSTEM_VERSION=3 link=shared runtime-link=shared threading=multi
Run Code Online (Sandbox Code Playgroud)
为了确定project-config.jam中的参数,我使用ndk-build构建了一个示例共享库,获取了它的调试消息,并提取了它使用的编译和链接命令.
编译:
C:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++.exe,C:/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi/objs/someLib/./Unity1.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector …
Run Code Online (Sandbox Code Playgroud) 我从服务器端应用程序获得valgrind泄漏报告,该应用程序使用与boost 1.56一起分发的boostlog.valgrind报告是:
== 8021 == 1,159块中的37,088字节肯定会在1,642的损失记录1,613中丢失
== 8021 ==在0x4A05588:memalign(vg_replace_malloc.c:727)
== 8021 == by 0x3FDA61118F:tls_get_addr_tail(在/lib64/ld-2.12.so中)
== 8021 == by 0x3FDA61165F:__ tls_get_addr(在/lib64/ld-2.12.so中)
== 8021 == by 0x3FE6ABBDCB:__ cxa_get_globals(在/usr/lib64/libstdc++.so.6.0.13中)
== 8021 == by 0x730C528:boost :: log :: v2_mt_posix :: aux :: unhandled_exception_count()(在/opt/sesteksdk/lib/libboost_log.so.1.56.0中)
== 8021 == by 0x5D54D1F:sestek :: mrcp :: audio :: recognition :: AsynchronousRecognizer :: Notify(sestek :: voice :: recognition :: IRecognizerNotification const*)(record_ostream.hpp:259)
这种泄漏来自一条简单的线路:
LOGGER(debug)<< _chanProp->GetId() << " got recognition ended notification from recognizer";
我们从一次短暂的测试运行中得到了5个泄漏.
我们使用文本文件后端,同步接收器,自动刷新打开.基本上:
void InitializeFileLog(const std::string & logDir)
{ …
Run Code Online (Sandbox Code Playgroud) 我有一个类,通过它我可以异步提供一些服务(同样的调用也可以同步进行).当请求时,此类的对象(比如运算符)在另一个线程中启动操作.其他对象可以注册到操作符对象的通知,以便在操作结束时对此对象调用OperationEnded()方法.其他对象也可以通过调用操作符对象上的Wait()来等待此操作的完成.
操作结束时的代码大致如下:
_opEndedMutex.lock();
_thereIsOngoingOp = false;
_opEndedCondition.notify_all();
_opEndedMutex.unlock();
//no more call after notification
m_spNotificationManager->OperationEnded();
Run Code Online (Sandbox Code Playgroud)
而wait()函数如下:
boost::unique_lock<boost::mutex> lock(_opEndedMutex);
while(_thereIsOngoingOp)
{
_opEndedCondition.wait(_opEndedMutex);
}
Run Code Online (Sandbox Code Playgroud)
问题在于资源管理.这是一个C++类,因此当检测到操作结束时,此类的用户可能会删除操作符对象(如果存在任何活动操作,析构函数将等待完成).可以通过等待或接受通知来检测操作的结束.因此,如果我首先调用_opEndedCondition.notify_all()并且用户删除操作符对象,则在尝试调用OperationEnded()时可能会崩溃,因为m_spNotificationManager已被删除.如果选择首先调用OperationEnded()并且用户在此调用期间删除操作符对象,则在尝试访问_opEndedMutex,_thereIsOngoingOp和_opEndedCondition时可能会崩溃.
我想到的第一件事就是使用新的互斥锁来保护这两个调用.这看起来并不漂亮,因为我无法预见如果引入新的互斥锁会发生什么,并且如果在OperationEnded()通知中用户同步启动新操作.我也不确定如何在wait()方法中使用新的互斥锁.
注1:此API用于我们自己公司和其他公司的应用程序.所以我无法摆脱任何一种同步机制.
注意2:我修改了原始代码,变量和方法名称,因此可能存在拼写错误,但这个想法应该是明确的.
EDIT1:
操作员对象保留在通过工厂生成的共享库中,然后通过接口暴露给外部世界.所以操作符对象的典型生命周期如下:
IOperator * op = factory:getNewOperator();
//perform operations with op
op->Release() //this one goes and deletes the op object
Run Code Online (Sandbox Code Playgroud)
另请注意,运算符对象是可重用的.客户端代码可以使新的操作符对象多次使用它并在最后删除它.