6 ms·
So it will admit any combination of -n and -x. In particular, these things won't raise an error: find - hello find - - hello find -xnxn hello
by yongjik 9y ago
So it will admit any combination of -n and -x. In particular, these things won't raise an error:
find - hello
find - - hello
find -xnxn hello
find -x -n -x hello
find -xxx -nnn -xn hello
Yes, the code has an impressive logic density, but there's a reason why modern programmers moved away from such style.
- setr 9y agoWouldn't an empty flag be caught by the default handler? And duplicate flag usage isn't inherently incorrect (-vvv); handling that would be in the switch statement, and if its actually a boolean switch, then duplicates would just be ignored anyways, so harmless.
- kstenerud 9y agoThe empty flag(s) would be processed by *s != '\0' and result in noops. The point in the early days wasn't to handle corner cases like these gracefully. That only came later as the audience for shell commands widened.
- userbinator 9y agoIn particular, these things won't raise an error They don't necessarily need to be. Repeating the same option can either have no effect (|), invert the option (^), or increase something (as in -vvvvv.) IMHO it's a good thing when there are no error cases --- it basically means the entire input space has a defined effect.
- MaulingMonkey 9y agoRaising an error is an intentionally defined effect. Doing something under-defined, by accident, that you'll at some point break because you weren't thinking of that specific edge case when e.g. refactoring, for someone else who didn't actually intend to exercise that edge case but never realized they were doing so as they never received an error... well, not my cup of tea.
- candiodari 9y agoAnd causing errors for everything will cause your program to bug out in perfectly valid cases. Defensive versus total programming. Either have their place, but ... Thing is most programmers vastly overestimate the case for defensive programming. In practice, most programs need to run. So for instance, the control loop for a nuclear reactor is not defensively programmed. It never, ever, ever gets to yield an error. Why ? Because the system is not "fail-safe". If the program ever were to say "this doesn't make sense, I'm quitting (or otherwise doing nothing)", there is nothing guaranteeing the system is in a safe state, and so it may melt down. A bug that fails to notice a critical condition, and ignores it, on the other hand leaves the system under the control of the operator, and nothing (should) go wrong (meaning the second level checks should catch the problem) The general guideline is defensive programming when starting up, with a force switch to override it (so the system can be (re)started if operators decide that's the best outcome). Once the program is running, total programming should be your go-to solution. When in doubt, do the best you can and continue on to the next request. Since I've been programming million qps+ systems, I've learned that there's even nothing wrong with almost totally ignoring errors. You'd be surprised how well the following works: before handling a request, note down the time (using the cheap instruction), then every time you leave your method, check the time. If it's over a timeout, increase a counter, log if not logged in the past 10s, and send an empty reply. This makes the developer's job harder, but makes everybody else a lot happier.
- MaulingMonkey 9y ago> And causing errors for everything will cause your program to bug out in perfectly valid cases. Erroring out is admittedly not a panacea to every situation, but the user-facing end of a command line interface is pretty low hanging fruit and a pretty obvious place to error out. The nuclear reactor equivalent wouldn't be the low level control loop, it'd be how the display panels react to operator inputs and sensors - the red lights they turn on, the klaxons they sound, the systems they engage to attempt to put the reactor into a safe state when it thinks it's getting ready to melt down. And even for that low level control loop, you'd better believe they're thinking very very hard about, and once again intentionally define, how they handle any edge cases they can think of, not just throwing caution to the wind and letting the program's behavior fall where it may. Even for a rocket, sometimes the best answer is "do nothing - and let the range safety systems blow the damn thing up if that wasn't the right answer." > Since I've been programming million qps+ systems, I've learned that there's even nothing wrong with almost totally ignoring errors. You'd be surprised how well the following works: before handling a request, note down the time (using the cheap instruction), then every time you leave your method, check the time. If it's over a timeout, increase a counter, log if not logged in the past 10s, and send an empty reply. This makes the developer's job harder, but makes everybody else a lot happier. Totally ignoring errors leaves you with crashy garbage that does not accomplish your goal of high uptime/availability/not corrupting data in C++ - I'd wager you're dealing with safer languages to type that with a straight face! Even there, though, you probably write code to at least handle null references and other edge cases. You might not trigger fatal assertion dialogs, you might not log to some fancy telemetry system, you might not even log at all - but something to handle error conditions. And if you're writing that code anyways, you might as well write some logs/telemetry as well to make your devs lives easier. You don't have to force it into the face of your end users, you don't have to make the whole thing explode in the face of adversity, but some opt-in dev tools for yourself tends to be nice. A fun trick from gamedev: "Assertion" macros that force you to include an error handling statement (often a simple "return;"). Devs get to check out if that null pointer passed to your leaderboards is a systemic bug that broke all leaderboards, gamers get to keep their quest progress instead of the entire game crashing because a server being down or giving a malformed response means the game doesn't know how to handle updating a single leaderboard occasionally. Best of both worlds. Be greedy - you can have happy users and devs.
- kqr 9y agoThis is something that intrigues me about well-written low-level code. If you make some concessions on expected behaviour, the code can be really clean and simple. But you have to know which concessions are acceptable yet yield this result, and that's super hard, at least to me.
- pjmlp 9y agoWorse, if someone else has to change the code, even if that someone is author a few months/years later, those concessions will be unknown, breaking the code in strange ways very hard to debug.
- jstimpfle 9y agoDon't forget that the code is now trivial: It's easy to see corner cases since the logic is so small and therefore quite "round". There is not really room for code "breaking in strange ways". It's rather that we can now think more mathematically and more uniformly about the program's behaviour. It doesn't matter anymore if a given curiosity (like "-" options) is categorized as a concession or just as the way it's supposed to be. In any way it's the way that makes more sense from a mathematical standpoint. If there really was some client code depending on a curiosity, it's also easy to spot and change. But usually that's not even needed.
- jstimpfle 9y agoIt wouldn't be difficult to disallow these cases, but is that a problem after all? My opinion is that the requirements should be shaped (also) by what logic is required on the implementation side. And in any case, there's no justification to change the style and make an incomprehensible thicket of vague "abstractions". There's at most one to write slightly more logic.
- Someone 9y agoIf you want to, you can handle that in the switch statement: case 'x': if(x_set) { fprintf(stderr, “can’t set x twice”); err = 1; } else { x_set = true; } break; If your machine has 64kB of memory or thereabouts, you may choose to not bother, though.
- attractivechaos 9y agoIf you learn getopt, you will know having -x multiple times is not an error. It is a feature. For example, you can specify multiple files of the same type with one option. I agree silently ignoring those empty "-" is not desired.