← Back to context

Comment by fluoridation

2 days ago

The whole point of the optimizer is that it can detect inefficiencies by treating every statement as some combination of simple, fundamental operations. The compiler is not seeing "call memset() on pointer to heap", it's seeing "write of variable size" just before "deallocation". For some, optimizing that will be a problem, for others, not optimizing it will leave performance on the table.

There are still ways to obtain the desired behavior. Just put a call to a DLL or SO that implements what you need. The compiler cannot inspect the behavior of functions across module boundaries, so it cannot tell whether removing the call preserves semantics or not (for example, it could be that the external function sends the contents of the buffer to a file), so it will not remove it.

A modern compiler may also completely remove malloc / free pairs and move the computation to the stack. And I do not see what this has to do with C, it should be the same for most languages. C gives you tools to express low-level intent such as "volatile", but one has to use them.

  • Strong disagree. In C, malloc and free are functions, and I expect no magic to happen when calling a function. If malloc and free were keywords like sizeof, it would have been different.

    • Your problem is that you're treating words such as "function" and "call" as if they had meaning outside of the language itself (or, more specifically, outside of the C abstract machine), when the point of the compiler is precisely to melt away the language parts of the specified program and be left with a concrete program that matches its behavior. If you view a binary in a disassembler, you will not find any "functions" or "calls". Maybe that particular architecture happens to have a "call" instruction to jump to "functions", but these words are merely homophones with what C refers to as "functions" and "calls".

      When you "call" a "function" in the source you're not specifying to the compiler that you want a specific opcode in the generated executable, you're merely specifying a particular observable behavior. This is why optimizations such as inlining and TCO are valid. If the compiler can prove that a heap allocation can be turned into a stack allocation, or even removed altogether (e.g. free(malloc(1ULL << 50))), the fact that these are exposed to the programmer as "functions" he can "call" poses no obstacle.

      2 replies →

    • In C, malloc and free used to often be macros.

      As they're freely replaceable through loading, and designed for that, I would strongly suggest that are among the most magical areas of the C standard.

      We get a whole section for those in the standard: 7.24.3 Memory management functions

      Hell, malloc is allowed to return you _less than you asked for_:

      > The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and size less than or equal to the size requested

      5 replies →