5

Just to give a context, this is a simple version of my code:

class myqueue
{
   struct readable
   {
       readable()
       {
          static int __next = 0;
          id = __next++;
       }
       int id;
   };
   std::list<readable> readers;
   public:
      readable& sub(){
          readers.emplace_back();
          return readers.back();
      }
      void unsub(readable& reader)
      {
        for (auto it = readers.begin(); it != readers.end(); ++it)
        {
            if (it->id == reader.id)
            {
                readers.erase(it);
                break;
            }
        }
      }
};


int main()
{ 
   myqueue q;
   auto& read = q.sub();
   q.unsub(read);
   return 0;
}

With this code, after the call to unsub(), the reference you got from sub() is no longer valid, right?

Is there a better (secure) way to handle this situation and be sure noone will keep using that reference?

The first alternative I can think of is to check for the validity at runtime using pointers instead of references, but it's something you have to do explicitly every time and you can also skip/forget that. It would be great to be able to catch any use of that reference after the unsub() at compile time (something like Rust do after moving objects).

Is there any way to achieve this?

I think this is pretty simple to do logically:

  1. Get something from sub()
  2. use it
  3. call unsub()
  4. if that something appears again in this block => XXX

Probably with a static analyzer is simply doable, I was just wandering if I can achieve this during the compile.

Federico
  • 743
  • 9
  • 22
  • Maybe [this](https://stackoverflow.com/a/2524892/13433323) answers your question? – Sprite Jul 09 '21 at 10:28
  • You could not give the caller a `reader`, but rather return them an opaque struct pointer as a token that maps to the reader. After the reader is destructed, then passing in the dud token have your code throw. – Eljay Jul 09 '21 at 12:08
  • @Sprite: no, it doesn't actually, it does not say how to prevent this situation. – Federico Jul 09 '21 at 12:33
  • @Eljay: Yeah, i could, but this is again something happening at runtime, too late. – Federico Jul 09 '21 at 12:33
  • One solution would be a more RAII design: `sub` returns some object (or becomes the constructor of some other class), and `unsub` is replaced by the destructor of that object. – Nate Eldredge Jul 09 '21 at 12:51
  • @NateEldredge that's a good hint for an alternative solution, I'll look into it. – Federico Jul 09 '21 at 13:04

0 Answers0