Hi, Once again, the more I try to understand how GC works at the C++ level, the more I get lost. Of course, not being too good at low-level programming doesn't help. Take this random exported function:
LY_DEFINE (ly_duration_less_p, "ly:duration<?", 2, 0, 0, (SCM p1, SCM p2), R"( Is @var{p1} shorter than @var{p2}? )") { auto *const a = LY_ASSERT_SMOB (Duration, p1, 1); auto *const b = LY_ASSERT_SMOB (Duration, p2, 2); if (Duration::compare (*a, *b) < 0) return SCM_BOOL_T; else return SCM_BOOL_F; } This is my understanding: Duration is a Simple_smob type. That means a Duration object can be allocated either on the stack or on the BDWGC heap. Since p1 and p2 are SCM, they are BDWGC-heap-allocated in this case. The unsmobbed a and b are thus pointers to data on the BDWGC heap. Since they are pointers to the part of the SCM that stores the C++ object, and not to the start of the SCM value, they won't cause the SCM to be marked by their mere existence on the stack. p1 and p2 are not used after the LY_ASSERT_SMOB calls. The compiler could drop them before the end of the function. In that case, nothing protects p1 and p2 between the two LY_ASSERT_SMOB lines and the Duration::compare. If the ly:duration<? call is a tail call, Guile itself might not hold references to the duration objects. If that happens, a crash would ensue. This pattern looks somewhat frequent, so I hope I am wrong. If so, where is my mistake? Thanks in advance, Jean