5

我有一个奇怪的错误,我找不到它来自哪里。logcat 中出现的唯一内容是:

01-10 17:07:10.665: A/libc(20449): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

当我运行我的应用程序时,我不会立即收到此错误,我会在随机时间(1 分钟到 5 分钟之间)后收到它。我无法重现此错误,它似乎是随机的,并且由于没有其他信息,因此很难调试。我试图将一些日志信息添加到我的库中,但我仍然无法说出崩溃发生的位置。

我运行同一个应用程序 x 次,我得到了不同的 SIGSEGV 地址(有时它与以前的地址相同:

01-10 17:29:04.650: A/libc(21588): Fatal signal 11 (SIGSEGV) at 0x6c707063 (code=1)

01-10 17:25:55.165: A/libc(21473): Fatal signal 11 (SIGSEGV) at 0x0069004c (code=1)

01-10 17:11:58.780: A/libc(20742): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

01-10 17:00:02.010: A/libc(20160): Fatal signal 11 (SIGSEGV) at 0x00000018 (code=1)

我的应用程序正在使用具有从服务器接收更新的 NetworkThread 的 c++ 库。在 Java 端,有一个 WorkerThread 检查是否有来自 NetworkThread 的新更新,如果有新更新,它会通知所有侦听器。我还有一个 LocationSpotter(在 Java 端),它会在更新位置时进行一些 JNI 调用。

有没有办法调试这个或使用我从 SIGSEGV 获得的地址来调试应用程序?此外,我正在使用共享 JavaVM 对象来检索当前的 JNIEnv(并调用 AttachCurrentThread)。那个线程安全吗?

我注意到在收到 SIGSEGV 错误后(在应用程序实际崩溃之前),我仍然收到来自 NetworkThread 的更新。这意味着 NetworkThread 可能正在工作。

我还注意到一行可能是我的问题的根源(在 notifyAll 方法中),因为在 SIGSEGV 之前打印的最后一条消息是 "notifyAll1" :

for (unsigned i = 0; i < listeners.size(); i++) {
    try {
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll1");
        if (listeners.at(i) == NULL)
            __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");


        listeners.at(i)->update(u); // <- This line is a potential suspect
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2");

日志猫:

01-10 17:07:10.665: I/FROM C++(20449): notifyAll1
01-10 17:07:10.665: A/libc(20449): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)

然后我尝试在每个侦听update器方法的第一行打印一个日志,但没有一个被打印(我认为这真的很奇怪)。

任何帮助将不胜感激

4

3 回答 3

5

大多数情况下,当您尝试访问当时未创建的任何对象时,都会发生致命信号错误。因此,请正确检查它们。

于 2013-07-25T09:02:15.300 回答
1

我相信你应该像这样重写notifyAll循环:

for (unsigned i = 0; i < listeners.size(); i++) {
  try {
    __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll1 i=%u", i);
    auto listener = *listeners.at(i);

    if (&listener == NULL) {
      __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");
    }
    else {
      __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2 : listener[%u] at %p", i, &listener);
      listener.update(u);
    }
  • 在您的原始代码中,检查仅打印到日志,但update()仍然会失败(@Robin注意到了这一点)
  • 在您的原始代码中,侦听器可能会在 check 和update()之间获得无效的 NULL
  • 即使在上述更改之后,如果listeners.at(i)指向的侦听器对象变得无效, update()也可能崩溃。

但是有可能由于异常处理而发生崩溃。你没有透露catch(...)代码,所以我不能谈论这个。

于 2013-12-29T12:37:59.800 回答
0

似乎很明显

if (listeners.at(i) == NULL)
            __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");


        listeners.at(i)->update(u); // <- This line is a potential suspect
        __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2");

应该

if (listeners.at(i) == NULL) {
    __android_log_print(ANDROID_LOG_INFO, "FROM C++", "LISTENER NULL");
} else {
    listeners.at(i)->update(u); // <- This line is a potential suspect
    __android_log_print(ANDROID_LOG_INFO, "FROM C++", "notifyAll2");
}
于 2013-11-27T05:52:20.737 回答