Open Xeverous opened 2 years ago
I've reproduced the same error on macOS with clang. I guess you also used the same systemc-build with quickthread, which could explain why there are still 4 objects left. The deep reason is how SystemC implements the coroutine. With quick-thread, each sc_thread would have its own call-stack, allocating from the heap memory directly. When simulation is done, all the allocated memory part would be freed naturally. But if there is still some smart pointer on the callstack, this memory free cannot know it, which causing the leak. For this example, it's cleared that if an object has a smart pointer referred, and if the smart pointer is on the stack, it will leak. For example, consumer1/2/3 both has a ptr stored on the stack part, and the last object referred by those stacks(13/23/33) will be leaked. On the other hand, the producer2 would also hold a smart pointer for the object created, the value of which is 25, leading to leak finally. So in the end, 4 objcts are leaked. This leaking is hard to resolve with quickthread. Maybe you can try systemc with pthread solution, with a performance drop as the cost. But I think the leak will only happens when simulation is stopped iin the end, so this may not be a problem from this perspective, since OS would help to de-allocated all the leaked resource finally.
I see 3 possible solutions:
1) (ideal) just support C++11 and move semantics
2) use "a more correct" implementation (I don't know much about the inner workings of SystemC so it can be just wishful thinking, on the other hand it would be great if it was just a bug)
3) (probably high cost or impossible given API constraints) rewrite the implementation to fully support C++ semantics. I'm suspicious something shady is happening inside because the execution itself is single-threaded AND it can perform arbitrary jumps without use of exceptions - just like in my example, the library is able to exit an infinite loop. I have no knowledge of quickthread but the potential usage of some call stack shenanigans might be the reason for the library's magic ability to exit "unexitable" code and to break lifetime semantics. I'm still surprised that the specification allows (or forces) an API that has to tamper with the call stack. I would like to see at least a justification why it's designed this way (magic jumps) and not something like while (sc_core::is_running())
.
The magic ability to jump without exception is implemented with assemble code, instead of using existing API, in quickthread cases. The concept of this, known as coroutine, has just been introduced into C++ for C++20(and C++20 defines a stackless coroutine). I wonder if the Systemc could be rewrite with standard solution if possible, but it seems cost too much.
I do business with her as well, but she has asked me to keep those dealings private for now...
I'm more concerned with the fact that SystemC specification (which defines an API for implementers) has never been updated even to reflect C++11. The design of the API still stays on 90/03 level.
I have a project in work where we manage some objects using fifo and because systemc API does not support move operations there is a problem with expensive and/or move-only objects.
Currently the issue is resolved by very ugly code like:
I would like to avoid pointer/lifetime issues yet I know that API is designed only with C++98/03 in mind. So I tried to use smart pointers which should keep any resources correctly managed.
I have made a reproducible example based on http://learnsystemc.com/basic/channel_fifo which showcases leaks - 4 objects remain even though I used only smart pointers:
execution log:
Using GCC Ubuntu 9.4.0-1ubuntu1~20.04.1