- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
There is a fundamental difference in memory allocation and therefore in cache performances as well as multi-threaded (due to core/cache pollution and synchronization] between the two approaches. Disccussing these ramifications is one of the topic I enjoy bringing up in any mid-level developer position.
Admin
Look at the bright side: No use-after-free error, no memory leaks. There are guaranteed to be some array out of bounds overflows though.
Admin
If you're a code monkey who doesn't care about performance, by all means use an array of structs in preference to a array of structs if it conserves precious brainpower. In the real world, memory accesses are often far more optimal using the SoA (arrays) pattern.
Admin
There is no programming language where you cannot write bad code, some just make it easier.
Admin
I support that's true, from a literal point of view . . . but I can assure you that a value is indeed returned. Whatever happens to be in register zero is by definition the return value.
Admin
By definition that's undefined behaviour. You may see what's in register zero, you may see some other register, you may see a fixed value, or demons may fly out of your nose and it would still be compliant with the C standard.
The specific compiler you are using may have some fixed way of handling return values without a return, and the rest of the code may even be written to expect that, but there are no guarantees that any other compiler or even a different version of the same compiler will do the same thing.
Much to the joy of the next doomed soul who tries to maintain this code.
Admin
int MAX_WTF_IN_CURRENT_CODESOD = CodeSODs[wtf_id];
Admin
There is a nice benefit on allocating memory like that; there will be actually only one allocation happening, all the sizes and offsets are fixed and calculated by the compiler, so it's super efficient compared to doing a bunch of allocs/frees. Downside is obviously that those static variables are singletons, which means they use up memory as long as the process lives plus you have to synchronize potential concurrent usages. However for small singleton allocations (a few MB), it's totally fine.
Admin
It's always a trip when programmers use a constrained subset of C (of all languages to constrain!) and then complain that it's too limiting.
Admin
I used to program like this.
When I was programming in BASIC in the 70's and 80's.
Admin
I don't really want to defend such code, but I think for this case it's safe to assume that
the code isn't multi-threaded (and never will be since probably much of it won't be thread-safe anyway)
the total data size is tiny (probably way less than 1 MB) so wasting some of it doesn't matter
for the same reason, it will all sit in L1 cache anyway so access patterns won't matter
even other software that does dynamic allocation sets hard limits on many sizes anyway, so fixed-size arrays will do
Sure, the code is bad (if only for the repeated indexing that is easy to mess up), but actually in practice it probably won't matter much (in contrast to the UB and other reasons that cause the crashing).
Admin
(sigh) I knew that I'd get called out for saying "register zero" but I'm just too much of a VMS fanboy.
Regardless, the function is defined as returning an int, so unless the caller declares it differently, then the caller will get a value returned to it.
Admin
The most 'interesting' part is 'bool'
Either they brought their own or the code isn't all that old (in the context of IRC anyway).
Admin
It is possible that the caller of useraddchan() will ignore the return value, whatever it might be, or cast it to (void) to make this explicit: "useraddchan(1337, 1984, 1);" as well as "(void)useraddchan(12345, 404, 0);" are possible - and it's how programmers usually treat poor int printf()...
Admin
I too have had the experience of seeing BASIC code written in other languages
Admin
If one were writing for high-reliabiluty hard real time for maybe safety-crtitical or life-critical process control like in aviation/aerospace, military, or medical applications, it would make sense to avoid dynamic memory allocations, but to eschew handy things like structs is taking it too far, and especially for something as mundane as a chat server.
Admin
My guess on maintenance mode--it's a matter of load. "Server crashes" are poor handling of overload.
Admin
Yeah, I'm with you. They'll get some sort of value in the return value register (RAX on x86-64, for example), but the origin and value of that, er, value, is totally undefined and may as well come from the Nasal Demon Underworld.
Admin
On the subject of the Easy Reader Version: ("Look, at least by avoiding dynamic memory allocations, there's a whole class of bugs they didn't expose themselves to. I mean, it's roughly equivalent to only using the bathroom at home because you don't want to risk the sanitation of a public restroom, but still. ")
There's some places I've been where that is by far the most sensible behaviour. Just sayin.
Admin
"but I think for this case it's safe to assume that the code isn't multi-threaded" A server that's not multi-threaded? So if there's no network activity, it blocks waiting for input?
Admin
I... I... I do this... 😔
Admin
A quick look at GitHub found 178 IRC server repositories.
Too many to choose from, so they rolled their own?
Admin
Or just minor code change might trigger changes in register allocation. Then the return value changes and you can not predict what it is. Or compiler flags are changed from debug to optimize for (speed/memory/whatever)
Admin
Same here. Public facilities are maintained inadequately by people of questionable quality doing questionable work. There is no good reason to not just hold it for a couple hours.
Admin
"Look, at least by avoiding dynamic memory allocations, there's a whole class of bugs they didn't expose themselves to. I mean, it's roughly equivalent to only using the bathroom at home because you don't want to risk the sanitation of a public restroom, but still. "
This is the default way of working when in embedded development, frankly.. ^_^ That said, there's nothing against using decently declared structures...
Admin
@Foo AKA Fooo -- Agreed about "probably" - but one should no0t make assumptions. All we have is the posted code snippet and the full world of possibilities.
Now about the cache.... It is not that the whole thing will fit, it is about what is on the same PAGE [typically 4KiB]. If one source [cpu] modifies a page and then another one attempts to use it, there must be a synchronization which is SLOW. Having "space" between them avoids this....
But in our hypothetical world, we don't know the usage patterns of out hypothetical multi-access...so there is insufficient information..
Now C/C++ (and a few others) provide the ability to have different heaps, and this is a big help.... unfortunately certain runtimes [I am looking at you .NET] do not have real support for this, which makes certain paradigms quite difficult.