
Am 05.03.2018 um 22:14 schrieb Duncan Coutts via Libraries:
On Sun, 2018-03-04 at 11:19 +0100, Ben Franksen wrote:
I had a program I was working on lately (darcs) crash with a segmentation fault after I made a seemingly harmless refactoring. The original code was
[...]
So I looked at the bytestring library to see if there was something that could explain the crash. I found that it uses accursedUnutterablePerformIO all over the place.
I renamed it that (from inlinePerformIO) to discourage people outside of the bytestring library from using it! Its use within the bytestring library has been audited multiple times by multiple people. We're really pretty confident at this stage that the way it is used in the library is sound.
That doesn't cover use of Data.ByteString.Internal I guess. Fair enough. Still, accessing the internals is what was done in darcs (a long time ago) and it worked fine until I came along and rewrote a harmless utility function (linesPS) that did /not/ access the internals nor uses any unsafe feature. Its only fault was that it is being called by another not quite so harmless function (betweenLinesPS); and that one didn't even call accursedUnutterablePerformIO, it just used to/fromForeignPtr. You can find the details in my other recent email in this thread where I posted a cooked-down example. I think this example makes it quite plain that fiddling with ByteString internals is /a lot/ more dangerous than normal low-level programming with raw pointers as in C (which I do a lot, btw, I know what I'm talking about). I am not sure what conclusions to draw. I understand the desire to get the ultimate performance. But if achieveing the last 15% means the code becomes so brittle as to be practically unmaintainable by mere humans I doubt they are worth the cost. Cheers Ben