4 ms·
I think it's telling that the very first example to use dynamic allocation has a memory corruption bug. struct { int n; char c[0]; } *foo = malloc(
by doty 17y ago
I think it's telling that the very first example to use dynamic allocation has a memory corruption bug.
struct {
int n;
char c[0];
} *foo = malloc(16); /* sizeof(*foo) probably 4, so 12 bytes follow */
foo->n = 16;
for(int i = 0; i < 16; i++) { /* puts 16 bytes after foo->n. oops. */
foo->c[i] = 'a' + i;
}
Not that I don't love C for terseness and power or appreciate the systems one can build in it, but seriously.
- jgrahamc 17y agoI noticed that too, and what's weird is that's not at all how you should do it. Since the char c[0] has zero size you can do sizeof on the struct so that you can do the malloc correctly. struct thing { int n; char c[0]; }; int i_need = 16; struct thing * foo = malloc(sizeof(struct thing)+i_need); foo->n = i_need; for (int i = 0; i < foo->n; i++ ) { foo->c[i] = 'a' + i; } And if your compiler won't let you do char c[0] you can do char c[1] and either blow a byte, or do the calculation correctly. Note that you have to be careful with this sort of allocation if you are on a machine that has certain alignment requirements (e.g. Sun).
- cpr 17y agoWell, being pedantic, that should be struct thing *foo = malloc(sizeof(struct thing) + sizeof(char) * i_need); since sizeof(char) isn't guaranteed to be 1 byte on all systems.
- jimbokun 17y agoThank goodness. I haven't programmed C in a long time, and thought I was missing something when I saw that code.
- Locke1689 17y agoHis warning against using #ifdef is also misplaced. I have written assembler (GAS) using the GAS x86 asm preprocessor to write portable x86/x86-64 assembly code in one file. Far simpler and shorter than writing the same code in two files. Basically, whenever he says "never" do something he means he doesn't like to do it. For example, his answer to not having a multi-level function break is a nested helper function. God no. That's one of the few times when it's correct to use goto. Edit: Ahh, he also advocated always using mmap instead of the standard file IO functions. Wow that's bad.
- mbreese 17y agoI'm curious: are the standard IO functions that much more efficient than a mmap'd file? What makes you choose one over the other? I usually just use standard IO, unless I have a large file that might be randomly accessed by multiple processes. In that case I'll use a mmap. But, I don't code in C very much anymore, so I was wondering how much of a difference there really is.
- Locke1689 17y agoMostly because mmap is not portable. If you're writing a Linux specific version of your code then mmap is fine. If you foresee running your code on other platforms then you shouldn't use it. Basically, there's a reason why it's called "standard" IO. Generally you shouldn't use system calls unless you are absolutely, 100% sure that your code will only ever need to work on one system.
- holygoat 17y agoI've worked on a project that successfully uses memory mapping on all the major OSes. mmap is (allegedly) portable across Unixes: http://opengroup.org/onlinepubs/007908775/xsh/mmap.html http://opengroup.org/onlinepubs/007908775/xsh/mmap.html and you can do the same thing (with a few more hoops) on Windows.
- Locke1689 17y ago
- zephjc 17y agoGive a man enough rope to hang himself, and he'll shoot himself in the foot.