char foo[123];
int x;
foo[124] = 10;
and: var foo [123]byte
var x int
foo[124] = 10;
In C, this surprisingly changes the value of x. (Well, it's undefined, so it could do anything!) In Go, the program crashes with the error that index 124 is out of bounds.C is the absolute best programming languages for programmers who don't make mistakes. I'm not one of them, and I've never met one of them. If it works for you, that's impressive!
Also, a disciplined C programmer will always keep the size of the buffer near the buffer itself.
For example, using something like this is perfectly safe (though, we can see the performance hit of those if-statements if used intensively):
struct buffer {
size_t size;
char *data;
};
void buffer_alloc(struct buffer *buf, size_t size) {
if (buf != NULL) {
buf->data = calloc(size, sizeof(char));
if (buf->data != NULL) {
buf->size = size;
}
}
}
void buffer_free(struct buffer *buf) {
if (buf != NULL && buf->data != NULL) {
free(buf->data);
buf->size = 0;
}
}
bool buffer_read(struct buffer buf, size_t offset, char *dest) {
if (dest != NULL) {
if (buf.data != NULL && offset >= 0 && offset < buf.size) {
*dest = buf.data[offset];
return true;
}
}
return false;
}
int main() {
struct buffer buf = {0};
buffer_alloc(&buf, 123);
char c;
buffer_read(buf, 124, &c);
buffer_free(&buf);
return 0;
}
It is possible to write safe C code, but it takes understanding of the language, sometimes of the compiler as well.The whole "There is no programmer who don't make mistakes" argument is fallacious at best.
C is like a chainsaw, there are certain rules on how to use it safely. Yes you can cut limbs with a chainsaw, that does not make the chainsaw useless.
There are some unavoidable footguns (notably around unintended integer promotions and overflow), but for four decades life-critical machinery like rockets, munitions, airplanes, heavy industrial equipment, automotive control systems ... and more have been controlled by C code, and the number of lives lost due to bugs you are complaining about are statistical noise.
It's been used extensively in products that could never be patched or updated after release, and could only be recalled, and yet I recall only a few instances when bugs lead to lives lost, and in at least one of those cases the culprit was identified to be something other than the language (i.e. those same errors or worse would have resulted even if a different language was used due to the dev process and architecture).
These bugs are not even a rounding error! So it would seem that writing safe C is ubiquitous. You're seeing the statistical noise and concluding it is representative of all software written in C, when you should be looking at all that noise and saying "is this all there is?"
Replace chainsaw with:
- knife
- guns
- C programming language
There are tools and methods (and a lot of discipline) to ensure safety in C: - compiler's sanitizers[0]:
- address: to detect out-of-bounds and use-after-free bugs
- pointer-compare, pointer-subtract: to detect invalid operation when pointers are non null
- shadow-call-stack: to detect return address overwrites (stack buffer overflows)
- thread: to detect data races
- leak: to detect memory leaks
- undefined: to detect undefined behaviors
- ...
- static analysis tools, like Splint[1]
Would you ride a motorbike without the proper protections (helmet, heavy jacket, ...) ?[0] - https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.h...
The principal issue with Go applications in my work continues to be the massive size of the executables.
> The principal issue with Go applications in my work continues to be the massive size of the executables.
That is certainly true in general case, however out of curiosity I went to see the size of containerd runtimes on my machine and:
-rwxr-xr-x 1 1001 121 46889792 Sep 22 2022 /usr/local/bin/containerd
-rwxr-xr-x 1 1001 121 9699328 Sep 22 2022 /usr/local/bin/containerd-shim-runc-v2
Does not seem that bad... (note that only the shim is launched per container, containerd process is a single systemd service)I do however wish Mongo offered the option: https://jira.mongodb.org/browse/SERVER-39325
We have contributed patches and bugfixes to jemalloc as well.
Problem with tcmalloc is fragmentation. Luckily I can then on aggressive decommit in some scenarios and that helps.