← Back to context

Comment by robalni

2 days ago

I don't know if there can be any memory safe languages. Programming is always unsafe because you can always make mistakes. The best we can do is to use tools that help us avoid the common mistakes.

As an example of that, the rust compiler helps the programmer to avoid many mistakes but it's still possible to use memory incorrectly and the tool is only safe as long as you use it as intended. You could say that C is safe too as long as you use it as intended and make no mistakes. The only problem is that it's hard to use it as intended and make no mistakes.

So let's think about what memory safety could mean. My understanding is that a memory bug is when you use memory in an unintended way. An example of that is when you write to memory after you have deallocated it, which means after you have decided not to use it any more.

No compiler or tool can make sure you don't write to or read deallocated memory, because whether it's allocated depends on what your intention is, and no compiler can read your thoughts. They can only give you a tool (like functions for allocating and deallocating memory or compiler checks) and hope that you will use that tool in a way that reflects your intention. One problem is that those tools are not always sufficient to keep track of your intentions and you may not always use them as intended.

Memory allocation is relative. In a sense, no program that runs under an operating system can use deallocated memory, because when they read or write to memory that has not been mapped to the process, they crash. In a sense, even "safe" rust can use deallocated memory; let's say you have an array of 10 integers and you decide that the fifth integer should not currently be used, you have then deallocated it on a level where the available tools can not help you, but you can of course still access that memory.

So again, everything is safe if you use it as intended and nothing is safe if you use it in other ways. Safety depends on how well the code matches your intentions. Remember that programming always happens in layers and no tool can cover all of them. It's not even clear what "all layers" would mean or how many there are in a program.

> but it's still possible to use memory incorrectly

Only by misusing unsafe. Using it in regular programs actually isn't that necessary. In languages like C you have unsafe code almost in every line.

> My understanding is that a memory bug is when you use memory in an unintended way

Memory safety rules are more strict and formalized than you think. Memory safety issues are typically reading uninitialized memory (or strictly speaking changing observable behavior based on contents of uninitialized memory), reading/writing memory after it have been freed (free/delete call or out-of-scope going for local variables), concurrent unsynchronized memory access.

> No compiler or tool can make sure you don't write to or read deallocated memory

I am author of a programming language, where you can't write to or read deallocated memory, unless you misusing unsafe.

> no compiler can read your thoughts

But many languages more complex than C have powerful features allowing telling the compiler your about intents. At least partially.

> Memory allocation is relative. In a sense, no program that runs under an operating system can use deallocated memory

You are mixing two different concepts. One is memory model of the abstract machine defined by the specification of a language and other is the OS processes model. They have much in common, but there are a lot of differences.

> So again, everything is safe if you use it as intended

Such mindset is considered harmful, since it provides an excuse to use languages where making mistakes is easy (like C).

  • Say I implement a dynamic array in the usual way with buffer, length, capacity. Currently the capacity is 50 and the length is 20. I access element 30 i.e. an unallocated element. Was that memory unsafe?

  • I think the point you missed or don't want to accept is that I think of all layers of memory management as the same thing just on different layers. Where you say that I mix different concepts, I say that it's just different layers of the same problem.

    So which layer should we care about? All of them? Yes, if we want the most safety.

    I will give you an example of how I can use memory incorrectly in "safe" rust. Let's say I have an integer that contains my age. Now I forget what the number was used for and I use it as shoe size. I have now used memory (the content of the variable) as something it was not intended for. Maybe you think this example is silly, but what is really the difference between using a float pointer as an int pointer and using age as shoe size? Another thing we could do is to use an index for one array as an index for another array. That's an example of using a pointer as the wrong type because an index is just a relative pointer.

    So if we want to care about all layers of memory safety then we have to care about not using ages as shoe sizes and indexes with the wrong arrays. "Memory safe" languages usually don't help us with that and therefore they don't give us total memory safety. I think "memory safety" is not a very useful term because all data in a program lies in memory and basically all bugs have something to do with using that memory in wrong ways.

    • > we have to care about not using ages as shoe sizes and indexes with the wrong arrays. "Memory safe" languages usually don't help

      In languages even slightly better than C one can create a wrapper type for int/float with additional semantics like age, shoe size or something else. Since they are different types, using one in place of other isn't possible. This doesn't solve all problems, but at least can prevent silly mistakes.

      4 replies →