Opened 6 years ago

#12264 new Bugs

queue<Apple*> can pop to Orange* even when Apples don't relate to Oranges

Reported by: Jacob Burckhardt <JBurckhardt@…> Owned by: timblechmann
Milestone: To Be Determined Component: lockfree
Version: Boost 1.61.0 Severity: Problem
Keywords: Cc:

Description

The following program successfully compiles, but I think it should give a compiler error since it is casting an Apple pointer to an Orange pointer. Apple and Orange have no inheritance relationship so I think the cast should be invalid.

#include <boost/lockfree/queue.hpp>

class Apple {};
class Orange {};

int main() {
   boost::lockfree::queue<Apple*> m_queue(1);
   Orange *orange;
   m_queue.pop(orange);
}

For the following program, g++ says "error: cannot convert ‘Orange*’ to ‘Apple*’". If someone forgets what type of object that are storing in boost::lockfree::queue then they could make the above mistake of trying to extract the wrong type and it would be helpful if the compiler and boost caught the error.

class Apple {};
class Orange {};

int main() {
   Orange *orange = new Orange;
   Apple *apple = orange;
}

When I make the following change, g++ says "error: cannot convert ‘Apple*’ to ‘Orange*’" for the first program:

diff --git a/include/boost/lockfree/detail/copy_payload.hpp b/include/boost/lockfree/detail/copy_payload.hpp
index 75b1b52..7679d50 100644
--- a/include/boost/lockfree/detail/copy_payload.hpp
+++ b/include/boost/lockfree/detail/copy_payload.hpp
@@ -35,7 +35,7 @@ struct copy_constructible_and_copyable
     template <typename T, typename U>
     static void copy(T & t, U & u)
     {
-        u = U(t);
+        u = t;
     }
 };

Even though that change helps my case by warning me of my error, I think it probably breaks other cases, but at least this might help in understanding the reason why the original version of lockfree does not give an error message. In my case, U is a pointer type. It looks like it is calling the U constructor but I'm not sure what it means to call a constructor of a pointer type. Apparently what it means is to perform some kind of dangerous cast like an old style C cast instead of one of the more safer types of casts like a newer C++ cast. Perhaps you can make lockfree use my change only when U is a pointer type, but use the old version of the code for non-pointer types?

I tested with g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)

I used this version of lockfree:

commit c112c29bee1d35089d4a603027dbbc4e1744d59b Apr 2 12:02:35 2016 +0200

Change History (0)

Note: See TracTickets for help on using tickets.