2

几个星期以来我遇到了一个问题,我需要知道我的直觉是否正确。我的 Android 应用程序正在使用 c++ 库,并且每隔一段时间就会触发一次 SIGSEGV 错误。

我有一个用 C++ 编写的 NetworkThread,它从服务器接收更新对象。我有一个用 Java 编写的 WorkerThread,它询问 NetworkThread 是否每 0.5 秒有新的更新。

我使用 SWIG 生成的 JNI 包装器在 c++ 和 Java 之间进行通信。

在 NetworkThread 中,我们有一个std::vector包含所有新更新的内容。

WorkerThread (Java) 使用这一行来获取一个新的 Update 对象:

Update u = nwt.nextUpdate();

然后在 NetworkThread (c++) 中触发以下代码:

Update NetworkThread::nextUpdate() {
    pthread_mutex_lock(&nwt_mutex);
    pthread_mutex_lock(&inQ_mutex); // RACING CONDITION
    Update c = inQ.front();
    inQ.erase(inQ.begin());
    if (inQ.size() <= QUEUE_SIZE) {
        pthread_cond_broadcast(&inQ_threshold_cv);
    }
    pthread_mutex_unlock(&inQ_mutex);
    pthread_mutex_unlock(&nwt_mutex);
    return c;
}

该行Update c = inQ.front();制作对象的浅表副本(更新不会覆盖 = 运算符)。我认为这很糟糕,因为 Update 包含对其他对象(和对象向量)的引用。

然后inQ.erase(inQ.begin());调用该行,从 std::vector 的文档中删除的元素被销毁。这是否意味着此时对 c 中的对象和向量的引用不再有效?

使用此 JNI 片段将 Update 对象发送回 Java 后:

    // Retrieve the current JNIEnv* with the cached JVM
    int status;
    JNIEnv* env;
    bool isAttached = false;

    status = gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2);
    if(status < 0) {
        status = gCachedJVM->AttachCurrentThread(&env, NULL);
        if(status < 0) {
            return;
        }
        isAttached = true;
    }

    jmethodID update = env->GetMethodID(gClazzUpdateListenerWrapper, "update", "(J)V"); // J stands for Java long type

    // Call Java method update from jUpdateListener object
    env->CallVoidMethod(jUpdateListener, update, (jlong)(intptr_t)&u); // Pointer as agument, we'll build the Update object in Java

    if (isAttached) {
        gCachedJVM->DetachCurrentThread();
    }

在这里,我向 Java 发送一个地址(长),然后像这样构建对象(我使用 SWIG 生成的默认构造函数):

    Player p1;

public void update(long ptrUpdate) {
    final Update u = new Update(ptrUpdate, false);
            p1 = u.getEntity(0).toPlayer();
            ...
    }

像我一样这样做是不好的做法吗?我认为用 long 这样做是不好的,但是如果地址已分配并且有效,那么应该没有任何问题吧?

无论如何,这似乎工作得很好,直到我收到一个 SIGSEGV 错误(没有更多信息),我怀疑这是因为我一直使用对已被销毁和收集的对象的引用。

4

0 回答 0