1
$\begingroup$

I have been witnessing some bizarre behaviour with my very simple node.

I have a custom message that contains uint8[] type (it's 8 elements long). I have a subscriber that subscribes to a topic of the custom message and stores it in a global variable:

uint16* leddar_distance_cm_1 = NULL;

void leddarCallback(const perception_msgs::Leddar8::ConstPtr& msg) {
  if (msg->leddar_id == 1) {
      leddar_distance_cm_1 = const_cast<uint16_t*>(&(msg->distance[0]));
  }

  for (uint8_t i = 0; i < 8; i++) {
      ROS_INFO("VALUE: [%d]", leddar_distance_cm_1[i]);
  }
}

int main(int argc, char** argv) {
  ros::init(argc, argv, "collision_avoidance_node");
  ros::NodeHandle n;

  ros::Subscriber leddar_sub = n.subscribe("perception/leddars", 1000, leddarCallback);

  ros::spin();

  return 0;
}

I then have 2 publishers publishing onto that topic using rostopic pub. When I try to print the stored array from the callback I get this (bottom right window):

enter image description here

As you can see the two publishers seem to be interfering with each other and somehow overwritting leddar_distance_cm_1 pointer repeatedly. This doesn't happen with any non-pointer types from the message such as char or int.

I even tried creating 2 different subscribers for each publisher, same issue! As if both publishers are overwriting the same memory address (which they in fact are). Does this have anything to do with queues? I have a feeling that I am not reading the array correctly. I have spent over 8 hours looking at this and I can't figure out what the problem is, if there is an obvious mistake could someone please tell me what it is?

$\endgroup$
2
  • $\begingroup$ possible cause .... google atomic write $\endgroup$
    – jsotola
    Jan 13, 2019 at 19:27
  • $\begingroup$ @jsotola, I am familiar with atomicity, I got this fixed, it was the message callback deleting itself so instead of using pointers I had to copy the data instead. $\endgroup$ Jan 13, 2019 at 19:51

1 Answer 1

1
$\begingroup$

The problem was that I was pointing a pointer to a memory address that gets free'd after the callback is executed.

Instead of using C style arrays I moved onto vectors, where leddar_distance_cm1 is std::vector<uint16_t leddar_distance_cm1(array_size, starting_value).

When using callbacks always copy rather use references or pointers, unless you know your object's lifecycle.

If you still want to use C array, use std::copy or memcpy.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.