packageRemoveSuccessHandler() 处的分段错误

segmentation fault at packageRemoveSuccessHandler()

我正在使用 M600pro 模拟器开发 DJI osdk 应用程序。

当我运行我的软件时,有时会出现分段错误 在 SubscriptionPackage::packageRemoveSuccessHandler()。

OSDK 版本为 3.6。

我想出了这个错误发生的地方。

我在 dji_subscription.cpp 中添加了 printf()s,如下所示:

void
SubscriptionPackage::packageRemoveSuccessHandler()
{
    printf("SubscriptionPackage::packageRemoveSuccessHandler 1\n");

  // Clean up
  // Step 1. Clear fields in TopicDataBase
  for (size_t i = 0; i < info.numberOfTopics; ++i)
  {
    printf("SubscriptionPackage::packageRemoveSuccessHandler 2(i:%d)\n",i);
    printf("sizeof topicList = %d\n",sizeof(topicList));
    printf("sizeof TopicDataBase = %d\n",sizeof(TopicDataBase));
    printf("topicList[i] = %d\n",topicList[i]);
    TopicDataBase[topicList[i]].freq   = 0;             //  <<<< SEGMENTATION FAULT OCCURS AT HERE
    printf("SubscriptionPackage::packageRemoveSuccessHandler 3\n");
    TopicDataBase[topicList[i]].pkgID  = 255;  // Set pkgID to invalid
    printf("SubscriptionPackage::packageRemoveSuccessHandler 4\n");
    TopicDataBase[topicList[i]].latest = NULL; // Clear data pointer
    printf("SubscriptionPackage::packageRemoveSuccessHandler 5\n");
  }

printf("SubscriptionPackage::packageRemoveSuccessHandler 6\n");

  // Step 2. Clean up package content, except packageID
  cleanUpPackage();

  printf("SubscriptionPackage::packageRemoveSuccessHandler 7\n");

  setOccupied(false);

  printf("SubscriptionPackage::packageRemoveSuccessHandler 8\n");
}

发生段错误时,标准输出如下:

STATUS/1 @ removePackage, L466: Remove package 1 successful.SubscriptionPackage::packageRemoveSuccessHandler 1
SubscriptionPackage::packageRemoveSuccessHandler 2(i:0)
sizeof topicList = 140
sizeof TopicDataBase = 735
topicList[i] = 104
SubscriptionPackage::packageRemoveSuccessHandler 3
SubscriptionPackage::packageRemoveSuccessHandler 4
SubscriptionPackage::packageRemoveSuccessHandler 5
SubscriptionPackage::packageRemoveSuccessHandler 2(i:1)
sizeof topicList = 140
sizeof TopicDataBase = 735
topicList[i] = 64
SubscriptionPackage::packageRemoveSuccessHandler 3
SubscriptionPackage::packageRemoveSuccessHandler 4
SubscriptionPackage::packageRemoveSuccessHandler 5
SubscriptionPackage::packageRemoveSuccessHandler 2(i:2)
sizeof topicList = 140
sizeof TopicDataBase = 735
topicList[i] = 14290160
Segmentation fault

是这个sdk的问题吗?还是我的错?

不清楚 TopicDataBase 包含什么,或者它的大小是多少,但是 14290160 几乎可以肯定不是其中的有效索引:

TopicDataBase[topicList[i]].freq   = 0; // topicList[i] is 14290160

使用 gdb,我触发了分段错误并成功打印了 topicList 的内容,如下所示:

SubscriptionPackage::packageRemoveSuccessHandler 3
SubscriptionPackage::packageRemoveSuccessHandler 4
SubscriptionPackage::packageRemoveSuccessHandler 5
SubscriptionPackage::packageRemoveSuccessHandler 2(i:2)
sizeof topicList = 140
sizeof TopicDataBase = 735
topicList[i] = 729312

Thread 1 "djiosdk-bridge-" received signal SIGSEGV, Segmentation fault.
0x000459e4 in DJI::OSDK::SubscriptionPackage::packageRemoveSuccessHandler (
    this=0xb2094)
    at /home/pi/Onboard-SDK-3.6/osdk-core/api/src/dji_subscription.cpp:832
832         TopicDataBase[topicList[i]].freq   = 0;
(gdb) p TopicDataBase
 = 0x882b0 <DJI::OSDK::Telemetry::TopicDataBase>
(gdb) p topicList[i]
 = 729312
(gdb) p sizeof(topicList)
 = 140
(gdb) p i
 = 2
(gdb) p topicList
 = {DJI::OSDK::Telemetry::TOPIC_HARD_SYNC, 40, 729312, 1601594222,
  1717985635, 1866673765, 1819244142, 1869182069, 1918980206, 1952804193, 144,
  64, 729216, DJI::OSDK::Telemetry::TOPIC_QUATERNION, 837,
  DJI::OSDK::Telemetry::TOPIC_QUATERNION, 729496, 1995883856, 729528,
  1995883856, 1995883856, DJI::OSDK::Telemetry::TOPIC_QUATERNION, 144,
  DJI::OSDK::Telemetry::TOPIC_QUATERNION,
  DJI::OSDK::Telemetry::TOPIC_ACCELERATION_GROUND,
  DJI::OSDK::Telemetry::TOPIC_GPS_FUSED,
  DJI::OSDK::Telemetry::TOPIC_QUATERNION, 62513, 728448, 1977251780,
  DJI::OSDK::Telemetry::TOPIC_QUATERNION,
  DJI::OSDK::Telemetry::TOPIC_QUATERNION, 28001,
  DJI::OSDK::Telemetry::TOPIC_QUATERNION,
  DJI::OSDK::Telemetry::TOPIC_QUATERNION}
(gdb)

我正在尝试使用此代码订阅:

// Subscribe Begin
bool Util::BeginSubscribe( int responseTimeout)
{
    int pkgIndex;
    int freq;
    int numTopic;
    bool enableTimestamp;
    bool pkgStatus;

    // ①Quaternion at 200 Hz 
    // ②Altitude from Valometer 200Hz
    // Telemetry: Verify the subscription
    ACK::ErrorCode subscribeStatus;
    subscribeStatus = gVehicle->subscribe->verify(responseTimeout);
    if (ACK::getError(subscribeStatus) != ACK::SUCCESS)
    {
        ACK::getErrorCodeMessage(subscribeStatus, __func__);
        return false;
    }

    // Subscribe to Quaternion at freq 200 Hz.
    pkgIndex                   = SUBSCRIBE_PACKAGE_INDEX_200Hz;
    freq                       = 200;
    TopicName topicList200Hz[] = { TOPIC_QUATERNION,TOPIC_ALTITUDE_BAROMETER  };
    numTopic        = sizeof(topicList200Hz) / sizeof(topicList200Hz[0]);
    enableTimestamp = false;

    pkgStatus = gVehicle->subscribe->initPackageFromTopicList(
        pkgIndex, numTopic, topicList200Hz, enableTimestamp, freq);

    if (!(pkgStatus))
    {
        return pkgStatus;
    }
    subscribeStatus = gVehicle->subscribe->startPackage(pkgIndex, responseTimeout);
    if (ACK::getError(subscribeStatus) != ACK::SUCCESS)
    {
        ACK::getErrorCodeMessage(subscribeStatus, __func__);
        // Cleanup before return
        gVehicle->subscribe->removePackage(pkgIndex, responseTimeout);
        return false;
    }
    return true;
}

我自己解决了。

这发生在我用 Ctrl+C 杀死程序后重新运行我的程序时。 所以我让我的程序捕获 SIGINT 信号,然后显式调用 removePackage()(如下所示)

vehicle->subscribe->removePackage(SUBSCRIBE_PACKAGE_INDEX_200Hz, responseTimeout);