Skip to content

Conversation

Copy link

Copilot AI commented Oct 27, 2025

BuildMessageSchema allocated a ROSField with new but never freed it. Each Parser construction leaked ~50 bytes. Repeatedly creating Parsers in a loop caused unbounded memory growth (9MB → 29MB over 50k iterations in the reported case).

Changes

  • Added std::unique_ptr<ROSField> root_field to MessageSchema to own the root field
  • Changed BuildMessageSchema to use std::make_unique instead of raw new

The field tree already stored a raw pointer to this field; now the schema owns the allocation and ensures cleanup.

// Before (leaked)
auto root_field = new ROSField(schema->root_msg->type(), topic_name);
schema->field_tree.root()->setValue(root_field);

// After (owned)
schema->root_field = std::make_unique<ROSField>(schema->root_msg->type(), topic_name);
schema->field_tree.root()->setValue(schema->root_field.get());
Original prompt

This section details on the original issue you should resolve

<issue_title>Possible Memory Leak in Parser object</issue_title>
<issue_description>Ubuntu 24.04.1 LTS
Version: 1.0.2-1noble.20250814.084246

Memory accumulates when creating Parser objects in a loop, even though the Parser goes out of scope at end of loop.


#include <fstream>
#include <iostream>
#include <string>
#include <memory>
#include <chrono>
#include <thread>
#include <rclcpp/serialized_message.hpp>
#include <rosx_introspection/ros_parser.hpp>
#include <rosx_introspection/ros_utils/ros2_helpers.hpp>

void print_memory_usage() {
  std::ifstream statm("/proc/self/statm");
  long size, resident;
  statm >> size >> resident;
  long page_size_kb = sysconf(_SC_PAGESIZE) / 1024;
  std::cout << "Virtual Memory: " << size * page_size_kb << " KB\n";
  std::cout << "Resident Memory: " << resident * page_size_kb << " KB\n";
}

int main() {
    using namespace RosMsgParser;

    const std::string topic = "dummy_topic";
    const std::string type = "std_msgs/String";
    size_t counter = 0;
    std::vector<uint8_t> buffer(1024, 0);
    // No leak
    // Parser parser(topic, ROSType(type), GetMessageDefinition(type));
    while (true) {
      std::string out;
      ROS2_Deserializer deserializer;
      {
        // leak
        Parser parser(topic, ROSType(type), GetMessageDefinition(type));
        Span<const uint8_t> span(buffer.data(), buffer.size());
        parser.deserializeIntoJson(span, &out, &deserializer, 0, true);
      }
      counter++;
      if (counter % 10000 == 0) {
        print_memory_usage();
      }
    }
    return 0;
}

Parser creation inside loop:

Virtual Memory: 12212 KB
Resident Memory: 9088 KB
Virtual Memory: 17236 KB
Resident Memory: 14080 KB
Virtual Memory: 22260 KB
Resident Memory: 19072 KB
Virtual Memory: 27352 KB
Resident Memory: 24192 KB
Virtual Memory: 32376 KB
Resident Memory: 29056 KB

Parser creation outside loop:

Virtual Memory: 7168 KB
Resident Memory: 4096 KB
Virtual Memory: 7264 KB
Resident Memory: 4096 KB
Virtual Memory: 7264 KB
Resident Memory: 4096 KB
Virtual Memory: 7264 KB
Resident Memory: 4096 KB
Virtual Memory: 7264 KB
Resident Memory: 4096 KB

From what I can decipher from valgrind the issue might be in BuildMessageSchema. I noticed very high memory usage in my generic bridge after it had been running in simulation for a day.</issue_description>

Comments on the Issue (you are @copilot in this section)

@facontidavide Thanks a lot, I will investigate

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix possible memory leak in Parser object Fix memory leak in Parser from unowned root_field allocation Oct 27, 2025
Copilot AI requested a review from facontidavide October 27, 2025 15:45
Copilot finished work on behalf of facontidavide October 27, 2025 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Possible Memory Leak in Parser object

2 participants