Re: MobI? Really?
On Tuesday, 21 September 2021 at 16:14:52 UTC, Chris_D wrote: Thanks for the replies. jfondren: Sorry, but I am talking about documentation. For me, online web pages don't qualify; they are in the cloud, unreal, with no substance. Does anyone really read 300 pages online, in a web browser? Of course not. I do! As far as I know, that's how most D users read the D docs. The docs do ship with DMD, though. On Windows, there's an `html` folder in the installation tree. I don't know how they're installed on other platforms.
Re: Program crash: GC destroys an object unexpectedly
On Tuesday, 21 September 2021 at 20:47:41 UTC, H. S. Teoh wrote: Век живи - век учись. А дураком помрёшь. :) "Век живи - век учись, всё равно дураком помрёшь." is correct version. :)
Re: Program crash: GC destroys an object unexpectedly
On Tuesday, 21 September 2021 at 20:47:41 UTC, H. S. Teoh wrote: And since stopper isn't used anymore after declaration, an optimizing compiler is free to assume that it's not needed afterwards, so it's not obligated to keep the reference alive until the end of the function. It was not obvious for me, I thought lifetimes always lasts until the end of a scope (main in this case).
Re: Program crash: GC destroys an object unexpectedly
On Tue, Sep 21, 2021 at 08:36:49PM +, eugene via Digitalmars-d-learn wrote: > On Tuesday, 21 September 2021 at 20:17:15 UTC, eugene wrote: > > > Now, change operation order in the main like this: > > Actually, all proposed 'fixes' > > - use stopper somehow in the end (writeln(stopper.sg0.number)) > - change operation order > - etc > > are strange. I mean it's strange (for me) that these > fixes make garbage collector behave as needed. It's not strange. You're seeing these problems because you failed to inform the GC about the dependency between Main and stopper. So it's free to assume that these are two independent, unrelated objects, and therefore it can collect either one as soon as there are no more references to it. And since stopper isn't used anymore after declaration, an optimizing compiler is free to assume that it's not needed afterwards, so it's not obligated to keep the reference alive until the end of the function. Since in actually there *is* a dependency between these objects, the most "correct" solution is to include a reference to stopper somewhere in Main. Then the GC would be guaranteed never to collect stopper before Main becomes unreferenced. T -- Век живи - век учись. А дураком помрёшь.
Re: Program crash: GC destroys an object unexpectedly
On Tue, Sep 21, 2021 at 08:17:15PM +, eugene via Digitalmars-d-learn wrote: [...] > ```d > void main(string[] args) { > > auto Main = new Main(); > Main.run(); > > auto stopper = new Stopper(); > stopper.run(); > ``` [...] > ```d > void main(string[] args) { > > auto Main = new Main(); > auto stopper = new Stopper(); > > Main.run(); > stopper.run(); > ``` [...] > Everything is Ok now, stopper is not collected soon after start. > So the question is how this innocent looking change can affect GC > behavior so much?... In the first example, the compiler sees that the lifetime of Main is disjoint from the lifetime of stopper, so it's free to reuse the same stack space (or register(s)) to store both variables. (This is a pretty standard optimization FYI.) So the line `auto stopper = new Stopper();` would overwrite the reference to Main, and the GC would see Main as an unreferenced object and may collect it at any point after the line `Main.run();`. In the second case, since the lifetimes of Main and stopper overlap, the compiler (probably) conservatively assumes that their lifetimes last until the end of the function, and so reserves disjoint places for them on the stack. This does not mean you're 100% safe, however. A sufficiently optimizing compiler may determine that since Main and stopper are independent, it is free to reorder the code such that the two lifetimes are independent, and therefore end up with the same situation as the first example. If Main really depends on the existence of stopper, I'd argue that it really should store a reference to stopper somewhere, so that as long as Main is not unreferenced the GC would not collect stopper. T -- What's an anagram of "BANACH-TARSKI"? BANACH-TARSKI BANACH-TARSKI.
Re: Program crash: GC destroys an object unexpectedly
On Tuesday, 21 September 2021 at 20:17:15 UTC, eugene wrote: Now, change operation order in the main like this: Actually, all proposed 'fixes' - use stopper somehow in the end (writeln(stopper.sg0.number)) - change operation order - etc are strange. I mean it's strange (for me) that these fixes make garbage collector behave as needed.
Re: Program crash: GC destroys an object unexpectedly
On Tuesday, 21 September 2021 at 20:17:15 UTC, eugene wrote: Now, change operation order in the main like this: ```d void main(string[] args) { auto Main = new Main(); auto stopper = new Stopper(); Main.run(); stopper.run(); ``` ``` d-lang/edsm-in-d-simple-example-2 $ ./test | grep STOPPER 'STOPPER' registered 5 (esrc.Signal) 'STOPPER' registered 6 (esrc.Signal) 'STOPPER @ INIT' got 'M0' from 'SELF' 'STOPPER' enabled 5 (esrc.Signal) 'STOPPER' enabled 6 (esrc.Signal) ``` Everything is Ok now, I don't think this is reliably OK. If you're not using Stopper later in the function, and if there are no other references to it, then the GC can collect it. It just has no obligation to collect it, so minor differences like this might prevent that from happening for particular compilers/options/versions. C# and Go have 'keepalive' functions to avoid similar behavior, and Java's just as aggressive about potential collection. It's just something that mostly doesn't matter until it becomes an incredibly weird bug with code like yours.
Re: Program crash: GC destroys an object unexpectedly
On Tue, Sep 21, 2021 at 07:42:48PM +, jfondren via Digitalmars-d-learn wrote: > On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote: > > I do not understand at all why GC considers those sg0 and sg1 as > > unreferenced. > > And why old gdc (without -Os) and old ldc do not. > > Conclusion: > > There's nothing special about sg0 and sg1, except that they're part of > Stopper. The Stopper in main() is collected before the end of main() > because it's not used later in the function and because there are > apparently no other references to it that the GC can find (because the > only reference is hidden inside the Linux epoll API). Quick and dirty workaround: keep references to those objects in static variables to prevent GC collection: auto myFunc(...) { static MyType* dontCollect = null; MyType* obj = new MyObject(...); dontCollect = obj; scope(exit) dontCollect = null; // may collect after function exits ... // function body goes here } T -- Verbing weirds language. -- Calvin (& Hobbes)
Re: Program crash: GC destroys an object unexpectedly
On Tuesday, 21 September 2021 at 19:42:48 UTC, jfondren wrote: On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote: There's nothing special about sg0 and sg1, except that they're part of Stopper. The Stopper in main() is collected before the end of main() because it's not used later in the function Okay, but how could you explain this then ```d void main(string[] args) { auto Main = new Main(); Main.run(); auto stopper = new Stopper(); stopper.run(); ``` ``` d-lang/edsm-in-d-simple-example-2 $ ./test | grep STOPPER 'STOPPER' registered 5 (esrc.Signal) 'STOPPER' registered 6 (esrc.Signal) 'STOPPER @ INIT' got 'M0' from 'SELF' 'STOPPER' enabled 5 (esrc.Signal) 'STOPPER' enabled 6 (esrc.Signal) ___!!!___edsm.StageMachine.~this(): STOPPER destroyed... !!! esrc.EventSource.~this() : esrc.Signal (owner STOPPER, fd = 5) this @ 0x7fc9ab1a9150 !!! esrc.EventSource.~this() : esrc.Signal (owner STOPPER, fd = 6) this @ 0x7fc9ab1a9180 ``` Now, change operation order in the main like this: ```d void main(string[] args) { auto Main = new Main(); auto stopper = new Stopper(); Main.run(); stopper.run(); ``` ``` d-lang/edsm-in-d-simple-example-2 $ ./test | grep STOPPER 'STOPPER' registered 5 (esrc.Signal) 'STOPPER' registered 6 (esrc.Signal) 'STOPPER @ INIT' got 'M0' from 'SELF' 'STOPPER' enabled 5 (esrc.Signal) 'STOPPER' enabled 6 (esrc.Signal) ``` Everything is Ok now, stopper is not collected soon after start. So the question is how this innocent looking change can affect GC behavior so much?... Misaligned pointers are one way to hide objects from the GC but in this case they really weren't relevant. For sure.
Re: Program crash: GC destroys an object unexpectedly
On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote: I do not understand at all why GC considers those sg0 and sg1 as unreferenced. And why old gdc (without -Os) and old ldc do not. Conclusion: There's nothing special about sg0 and sg1, except that they're part of Stopper. The Stopper in main() is collected before the end of main() because it's not used later in the function and because there are apparently no other references to it that the GC can find (because the only reference is hidden inside the Linux epoll API). More discussion: https://forum.dlang.org/thread/siajpj$3p2$1...@digitalmars.com http://dpldocs.info/this-week-in-d/Blog.Posted_2021_09_20.html Misaligned pointers are one way to hide objects from the GC but in this case they really weren't relevant. I just had a confused idea of the epoll API, because I'd only ever used it with a single static array that all epoll functions referenced, similarly to poll(). But actually epoll copies the event structures that you give it, and returns them on epoll_wait. That's wild.
Re: MobI? Really?
On Tuesday, 21 September 2021 at 16:14:52 UTC, Chris_D wrote: jfondren: Sorry, but I am talking about documentation. For me, online web pages don't qualify; they are in the cloud, unreal, with no substance. Does anyone really read 300 pages online, in a web browser? Of course not. You can download them to a local copy, and you can generate them locally. But usually I am not reading 300 pages but going to a specific part of the documentation to look a specific thing up, and there I'm usually online anyway. As a thing to read from beginning to end rather than a spot reference I think the current spec would be very wanting for a few reasons, like internal hyperlinks and little of the justificatory text that 'annotated' specifications tend to have. For a recent example, in https://dlang.org/spec/garbage.html it just says "Do not misalign pointers if those pointers may point into the GC heap". Why not? If you can get away with it on a particular architecture, maybe it's fine? Actually, it's a big deal. What I'd like is Perl's offline documentation. Just type 'perldoc perl' into a unix system and look at it. Or 'perldoc -f stat', 'perldoc -q columns'. Jordi Sayol: PDF! ePub! Now that's what I call documentation! But that's on SourceForge. My first port of call to learn about D was, and is, dlang.org, where the *only* links to the "D Programming Language Specification" in any downloadable format are for the Mobi. Chris I haven't had consistent results with requesting updates to the online docs, but you could try just adding a link to this page. There are other offsite links and they occasionally need tending to, as well. A more immediate place to make a change is https://wiki.dlang.org/The_D_Programming_Language , where it'd be very easily to slide a few extra links onto the 'D Language Specification' link at the top right. The wiki isn't only accessible through Community/Wiki; several of the Resources links on dlang.org also point to it.
Re: MobI? Really?
Thanks for the replies. jfondren: Sorry, but I am talking about documentation. For me, online web pages don't qualify; they are in the cloud, unreal, with no substance. Does anyone really read 300 pages online, in a web browser? Of course not. Jordi Sayol: PDF! ePub! Now that's what I call documentation! But that's on SourceForge. My first port of call to learn about D was, and is, dlang.org, where the *only* links to the "D Programming Language Specification" in any downloadable format are for the Mobi. Chris
Re: Why dtor are not executed when removing a struct from associative arrays?
On 9/21/21 2:06 AM, Tejas wrote: On Monday, 20 September 2021 at 18:13:53 UTC, Steven Schveighoffer wrote: On 9/20/21 10:22 AM, Tejas wrote: In case you still want to delete stuff deterministically despite what Steve said, I suggest you make your `struct` a reference and use `core.memory.__delete`(not recommended to use this carelessly, btw) Do not call `__delete` here, use `destroy`. `__delete` will attempt to deallocate the block, which likely will fail since the key comes before the value, and GC.free on an interior pointer (I think) fails. But if it succeeded, it would not be good. This leaves a dangling pointer inside the AA. Rehashing the AA likely would result in a memory corruption. If you use destroy, the destructor will be called by the GC as well, but a struct should properly handle destroying the .init value. It doesn't succeed when object is stack allocated, otherwise it works; that's why I suggested changing `S` to `S*`. Oh! I missed that subtle change. I thought you were deleting a pointer to S that lives in a `S[int]`. I still recommend against this because you can easily get a dangling pointer that way. Aside from that, if you are careful enough not to store a retrieved S* from the aa, you could do that. It will incur one extra allocation per element, which is not ideal. Using destroy should be the most effective and safest mechanism. -Steve
better c fibers
Hi there, I'm new in dlang I specially like betterC. I was hoping that d fibers would be implemented in without using classes, but there are not. Is there another way how to use async/await in dlang better c? Thank you for your help Abby