Fix two memory leaks in the collocator lookup

Every collocator lookup leaked a rocksdb iterator and 80 bytes of window sums:

CollocatorIterator takes the iterator that SeekIterator() gets from
DB::NewIterator(), but had no destructor, so the compiler generated one that
does not touch the raw pointer. The wrapper was deleted by its unique_ptr, the
iterator it wrapped was not, together with everything it pins.

get_collocators() allocated its fixed size sumWindow array with malloc() and
never freed it. It is a fixed size, so it lives on the stack now.

Measured with 20000 calls of get_collocators_as_json() on the test database:
3.63 kB per call before, no measurable growth at all afterwards. The 80 bytes
were per call regardless of the result size, which is what gave them away.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I1b1148ada81bd821784b8e327334fc3bafe29e1b
diff --git a/src/collocatordb.cc b/src/collocatordb.cc
index b46d536..30656fc 100644
--- a/src/collocatordb.cc
+++ b/src/collocatordb.cc
@@ -225,6 +225,10 @@
 public:
   explicit CollocatorIterator(Iterator *base_iterator) : base_iterator_(base_iterator) {}
 
+  /* Takes ownership of the iterator handed in by SeekIterator(). Without this
+     every seek leaked a rocksdb iterator and the resources it pins. */
+  ~CollocatorIterator() override { delete base_iterator_; }
+
   void setPrefix(char *prefix) { memcpy(prefixc, prefix, sizeof(uint64_t)); }
 
   void SeekToFirst() override { base_iterator_->SeekToFirst(); }
@@ -677,9 +681,9 @@
   std::vector<Collocator> collocators;
   uint64_t w2, last_w2 = 0xffffffffffffffff;
   uint64_t maxv = 0, sum = 0;
-  auto *sumWindow =
-      static_cast<uint64_t *>(malloc(sizeof(uint64_t) * 2 * WINDOW_SIZE));
-  memset(sumWindow, 0, sizeof(uint64_t) * 2 * WINDOW_SIZE);
+  /* fixed size, so it lives on the stack and cannot be leaked */
+  uint64_t sumWindow[2 * WINDOW_SIZE];
+  memset(sumWindow, 0, sizeof(sumWindow));
   int true_window_size = 1;
   int usedPositions = 0;