使用Realm时出现致命信号11(SIGSEGV),代码1

7

看起来这个错误是由本地代码中的bug引起的,这是由于在错误下面的“Build Fingerprint”中看到了“librealm-jni.so”的短语,这取决于Realm库。我安装了最新版本的Realm -- 1.2.0.

以下是错误代码:

Fatal signal 11 (SIGSEGV), code 1, fault addr 0x14c in tid 7837 (ator.app)

这里是“构建指纹(Build Fingerprint):”。
    Build fingerprint: 'generic/vbox86p/vbox86p:5.0/LRX21M/buildbot11172321:userdebug/test-keys'
26643-26643/? I/DEBUG: Revision: '0'
26643-26643/? I/DEBUG: ABI: 'x86'
26643-26643/? I/DEBUG: pid: 7837, tid: 7837, name: ator.app  >>> com.lockedout.app <<<
26643-26643/? I/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x14c
26643-26643/? I/DEBUG:     eax 00000148  ebx ffffffff  ecx 7470d340  edx 00000002
26643-26643/? I/DEBUG:     esi 00000000  edi 00000002
26643-26643/? I/DEBUG:     xcs 00000023  xds 0000002b  xes 0000002b  xfs 00000007  xss 0000002b
26643-26643/? I/DEBUG:     eip e2f6d025  ebp ffd3cd58  esp ffd3cd50  flags 00210246
26643-26643/? I/DEBUG: backtrace:
26643-26643/? I/DEBUG:     #00 pc 0002a025  /data/app/com.lockedout.app-1/lib/x86/librealm-jni.so
26643-26643/? I/DEBUG:     #01 pc 0009c141  /data/app/com.lockedout.app-1/lib/x86/librealm-jni.so
26643-26643/? I/DEBUG:     #02 pc 0009c299  /data/app/com.lockedout.app-1/lib/x86/librealm-jni.so
26643-26643/? I/DEBUG:     #03 pc 004002d3  /data/dalvik-cache/x86/data@app@com.lockedout.app-1@base.apk@classes.dex
26643-26643/? I/DEBUG:     #04 pc 00000002  <unknown>
26643-26643/? I/DEBUG: Tombstone written to: /data/tombstones/tombstone_06

更新:

我将问题缩小到在调用RecyclerView.Adapter上的notifyDataSetChanged之后发生,但是代码在执行完这个操作后没有做任何其他事情。因此,我进一步将问题区域缩小到了 Android 的 Looper 类中的第135行:

Message msg = queue.next(); // might block

我不确定这是什么意思,但我想知道了解 Realm 内部的人可能能够说明为什么在 Looper 中引发错误。

关于错误之前在 Realm 中发生的更多变化信息: notifyDataSetChanged 在设置在一个 RealmObject 上的 RealmChangeListener 中被触发,该对象名为 “User”。导致更改的事务从 UserRealmList<Item> 中删除了一个自定义的 RealmObject,即 “Item” 对象。我知道这是因为我的代码中唯一会发生的事务和操作。这是删除 Item 的代码:

RealmSingleton.getUserInstance().executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        UserSingleton.getUser().deleteItem(mItem.getClassId());
    }
});

更新:

导致错误的Realm代码确切行数为SharedGroup中的第149行:

148    void commitAndContinueAsRead() {
149            nativeCommitAndContinueAsRead(nativePtr);
150    }

我们需要知道这个方法在哪个线程上被调用,以及UserSingleton.getUser()是什么,它在哪个线程上,何时更新,如果您在UI线程上执行任何同步事务,以及在最坏的情况下,如果您在RealmChangeListener中使用同步事务。 - EpicPandaForce
@EpicPandaForce方法是从AsyncTaskonPostExecute回调中调用的,因此我认为这意味着它是从UI线程调用的。UserSingleton.getUser是UI线程上的RealmObject。在每个线程上,我的所有事务都是同步的,并且在任何RealmChangeListeners中都没有执行任何事务。 - shoe
@EpicPandaForce 我之所以只使用同步事务,是因为当我开始使用“Transactions”进行事务处理时,我使用了异步事务,但出现了一些错误。但是当我切换到使用同步事务时,所有问题似乎都得到了解决 - 这全部都在UI线程上完成。 - shoe
doInBackground()修改了User表吗? - EpicPandaForce
@EpicPandaForce 我说错了。这个方法并不是在AsyncTask的onPostExecute中运行,而是将更改发布到服务器的方法。Realm事务只是在RecyclerView.ViewHolder中的普通方法中运行,并且我没有使用异步查询。我记得你之前告诉过我这个方法,然后我尝试了一下,但我的应用程序崩溃了,所以最终我把所有的事务都变成同步的,这样问题就解决了。 - shoe
显示剩余3条评论
1个回答

1

(我仍然不是官方的Realm人员)

注意:为了真正回答这个问题,我需要看到完整的代码。毕竟,Realm处理大多数可能在本地端导致崩溃的情况,并将其作为异常抛出到Java中,因此您可能正在做某些非常错误的事情。:P

猜测:

1.) 您正在UI线程上使用异步查询和同步写入,从而创建分离的行访问器,然后尝试根据ID删除它,尽管它不是最新版本

(异步查询不会立即执行,您需要使用RealmChangeListener监听其完成,但如果您将它们与UI线程上的同步写入混合使用,则会强制查询变为同步。)

2.) 您在后台线程上修改了某些内容,但尚未在UI线程上更新RealmResults(通过looper运行事件处理),因此您尝试在事务中使用的元素不是最新版本,因此其删除会导致崩溃。

可能的解决方案:

a.) 当您在UI线程上工作时,请使用executeTransactionAsync()而不是executeTransaction()

b.) 在您的方法中

UserSingleton.getUser().deleteItem(mItem.getClassId());

不确定 UserSingleton 是什么,但在删除元素之前,您应考虑基于 ID 在事务内重新查询它,以获取该元素的最新版本(在这种特定情况下可能尚未更新,同步事务在 UI 线程上)。

可能的解决方案:

如果您想帮助 Realm,如果此崩溃可以重现,请考虑将项目发送到 help[at]realm.io,让他们查看并修复。毕竟,您应该得到 Java 异常而不是本地崩溃。


1
好的。我找到了导致错误的 Realm 代码确切行。它是 nativeCommitAndContinueAsRead(nativePtr); -- 在 SharedGroup 中的第149行。 - shoe
显然,如果我了解更多你的代码,我就能够知道为什么你对象的版本控制失败,并且在交易中指向不应该去的地方。顺便说一下,很好的发现,你以前没有其他人这样破坏过Realm:D你应该向help@realm.io发送一个示例。 - EpicPandaForce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接