C++ std::streambuf::pubseekpos(): check if random access is supported - c++

While writing a generic function taking a reference to an std::streambuf, I'd like to check if the supplied buffer is tied to something supporting random access or not and optimize the treatment accordingly, i.e. check if moving around the stream with pubseekpos() is available or not.
I might have overlooked that in the documentation. Would you happen to have a crystal clear solution, other than late-discovering if it works or not based on the result of the latter method (which returns -1 in case of failure to seek, which could have other causes)?
Available docs:
https://www.cplusplus.com/reference/streambuf/streambuf/pubseekpos/
https://en.cppreference.com/w/cpp/io/basic_streambuf/pubseekpos
Thanks in advance. Regards.
(Edit #GIJD after first comment)
Even if I'm not really glad about it, you've got a good point here. The same as "rather than testing if a file exists before opening it, open it and process error_status/exceptions" (as a race condition is always possible between the test and the opening otherwise).
OK, the actual function call by itself might indeed be the best proof over some feature flag existence test (that might also be wrongly set, even if unlikely if the code was tested duly... well, I just read what I wrote, yeah, well, as if code is always duly tested... OK ha ha, better test the function directly yes yes).
But, still, a -1 return value might mean error, not lack of random access, but one might argue that the result is the same, I won't be able to do random access if it fails whatever the reason, feature lack or some error. Thus, I'll have to fall back to a one-pass stream read anyway.
Thanks. Regards.

Related

What should a function return that can fail?

My question is a bit vague and that is at least partially intentional. I'm looking for early advice about interface design, future expansion and easy to test-interfaces and not too much about exact code. Although, if it's a solution/advice that applies especially to C++(17), then that's perfect.
I've a simulation that solves a hard combinatorial problem. The simulation propagates step by step to a solution. But sometimes, a step is a dead end (or appears as such). For example, in the pseudo code below, the while loop propagates the simulation by feeding it with pieces. There there can be a case where a 'Piece' can not be used to propagate the simulation. E.g. it's to expensive, it's a piece that simply does not fit or the for what ever reason. Failure is a normal behaviour that can arise an no reason to abort.
while(!allNotHandledPieced.empty())
{
auto nextPiece = allNotHandledPieces.back();
allNotHandledPieces.pop_back();
auto status = simulation.propagate(nextPiece);
if(status == 0)
next; // ok
else if (status == 1)
dropPieceDueToTooBadStatus();
}
Actually, for the 'simulation' it doesn't matter why it failed. The state is still valid, there is no problem with using another piece, it can just continue. But later, I might see the need to know why the 'propagate' method failed. Then it might make sense to have a meaningful return value on failure.
Is there a good way to return 'failure'? Is there a best practice for situations like this?
From what I can gather, it seems like neither exceptions or "returning" are appropriate for your situation. In your question you talk about "returning a result" but your particular code example/use case suggests that that the algorithm should not halt or be interrupted if a "bad piece" is used. Both exceptions and "returning" from a function will result in more complex control flow, and in some cases, more complex state handling depending on how you deal with exceptions.
If you choose the exception route, I suggest modeling your "reporting" classes after system_error.
If you choose a non-control flow route, I suggest pushing an error code and other meta data about the piece (if the piece itself is too expensive to copy around) into another data structure where it can be consumed.
What you choose to do depends on whether or not the bad piece requires immediate action. If it doesn't, exceptions are not the way to go since that implies it needs to be handled at some point.

Assert in try catch block

I am currently adding handling to a segment of code so that it will not crash. Currently it has each step then an ASSERT statement to make sure nothing went wrong in the previous step. If something went wrong in one of these steps something did go very wrong. The program should stop.
Though in release mode the program hits a assert, happily carries on its way and crashes.
To fix this I have wrapped the method in a try/catch block and throw errors where the asserts used to be. This should catch all the errors we track and others we do not.
Now my question is, should I still be using asserts to notify the programmer that this should not have happened? Or take them out now that it will not crash because of the catch block (where I cleanup the object)?
Or alternatively should I just throw an assert in the catch block instead of with each throw statement?
try & catch and assert has completely different purposes (at least in my view).
try and catch are used to cope with expected error conditions (user supplied a filename that doesn't exist, calling new couldn't allocate memory, user entered invalid input of some sort, etc).
The purpose of assert is the guarantee that the programmer doesn't make mistakes. Hopefully, when running the code in release, you'd have already covered those alternatives, and know that the code is "good". Typical examples of assert would be some pointer the user should not supply as NULL is indeed not NULL, or a linked list has the expected number of nodes [e.g. you count the number of nodes before remove_node, and check that the number of nodes is indeed exactly one less].
If you are NOT 100% certain (or at least 98.75% certain or whatever level you decide is "good enough") that you have tested all of your code, then you should not make the release - or if you do, get your quality assurance manager to sign off that "we haven't done enough testing, but we are OK with that".
try and catch should only be used for things your program can reliably recover from. Not to catch "programmer wrote stupid code that causes a crash".
Edit to clarify the actual answer:
In other words, yes, you should use assert for things that you don't expect to ever happen in the code [at least if the programmer is not doing things wrong] - this includes for example checking that the vector inside a vector for a matrix is indeed a square when you expect to have a square matrix, for example, or that pointers are not NULL [except where you expect them to be - and perhaps even check that they ARE NULL when they SHOULD be].
You should also use error checking with try/catch and throw when things go wrong that could well happen during the running of the actual program in "real life" - disk full (or read-only), files not existing, not enough memory, things of that sort.
Mats Petersson is quite right on assert. It's use is pre-release to check your internal logic. I won't repeat that point.
What I'd add, however, is let's suppose you want to check something else - for instance, check the result of something that should never go wrong, but might, for instance due to a problem in some other part of the system. In this instance, you should check for it (not using assert), and handle the situation gracefully. Normally the thing to do is throw an exception here, as you don't (normally) want the program to stop dead with no errors. Alternatively the thing itself with throw an exception. Often you want to carry on in a clean manner, but if you do want to stop, you almost certainly want to do some degree of clean-up first. That's what your catch block etc. is meant to do.
I think you use assert macros, which are excluded when in release mode, thats why your code runs happily through them. They are mainly used for a kind of debugging, during developement to make sure your program works well.
Think of them like they are saying:
this should never happen here, if it happens there's a bug in my code,
so I have to fix it
They tell you wheter you've made a (logic) mistake.
For example when you check for zero divisor:
int x = GetIntFromInput();
if (x != 0);
{
assert(x != 0);
float y = 10.0f / x;
}
This code has a sematic error, the ; behind the conditional. This assert will warn you during debugging/developement build.
Just use try/catch blocks if you want to create 'run-time' asserts, however I don't really like to throw them. Why should I not wrap every block in "try"-"catch"?. Maybe you can replace the exceptions with if-s or error codes.
Defensive programming consists of defining your assumptions at each line of code, and still checking them.
An Assert should explain "at this point, I honestly believe that this condition failing would be a sign that the system is in a state not expected by the programmer (me)".
Having the code then also check for the failure of the assumption, and early exit, is an example of defensive programming. But those failures should only occur in special-crafted unit tests that break the preconditions of various interfaces (with asserts disabled). If it happens in normal unit tests, or in normal use, or on user systems, then you need to move the protection against failure somewhere else, or make the failure an expected failure mode.
Depending on the severity of the assert, you should resist the temptation to "limp on" if things are going extremely wrong. State of the program should be backed up in a way that it could be restored, the user should be notified and encouraged to shut the program down. If your program can do irreversible operations, a forced shut down is more reasonable.
I have just realized that the question asked is not being answered. Rather than another lecture on what asserts and exceptions should and should not do, I'll address this: "Now my question is, should I still be using asserts to notify the programmer that this should not have happened?"
The answer is LOGGING. This should trigger an error log, which will be easily visible at the customer site, or at least to any of your people doing tech support.

Is it possible for a line of code that's not being called to cause a bug?

I'm currently dealing with one of the strangest bugs I have ever seen. I have this "else if" statement and inside the else-if I have a line of code that is causing a bug to happen elsewhere (my program is kind of complicated so I don't think it would help to post a short snippet of code here because it would be too difficult to explain -- so I apologize in advance if this post seems rather vague).
The issue is that the line of code that is causing the bug is not being called at all. I put a break point at the line and also put a print statement before it but the program never enters that particular "if-else" statement. The bug goes away when I comment out the line and shows up again when I uncomment it. This leads me to believe that the line must be getting called somehow but my break point and prints suggest otherwise.
Has anyone ever heard of something like this happening? Why would a line of code that is not even being called affect the rest of my program? Are there other ways to detect if the line is being called somehow besides using breakpoints and print statements?
I'm using XCode as my IDE and this is a single threaded program (so it's not some weird asynchronous bug)
PROBLEM HAS BEEN SOLVED. SEE TOP ANSWER
It actually may happen in some cases indeed and I already saw it before. If the bug is some slight buffer overflow then the presence/abasence of that line may make the compiler differently optimize the memory layout (ie. not allocate some variables or arrange them in a different way or place segments differently for example) that will by chance not trigger the problem anymore.
The same applies if the bug is a strange race condition: the lack of that line may change slightly the timings (due to differently optimized code) and make the bug come out.
Very long shot: that code may even somehow trigger a compiler bug. But this may be less the case, but it may.
So: yes it's definitely possible and I already saw it. And if something like this is happening to you and you're 100% sure your code is correct then be very careful since something quite nasty may be hiding in the code.
Not that there is enough information here to really answer this question, but perhaps I can try to provide some pointers.
Optimization. Try turning it off if it is turned on at all. When the compiler is optimizing your code, it may make different decisions when a statement is present vs. when it isn't. Whenever I am dealing with bugs that go away when a a seemingly unrelated code construct is changed, it is usually that the optimizer is doing something differently. I suppose a very simple example would be if the statement accesses something that the compiler would otherwise think is never accessed and can be folded away. The "unrelated" line may take an address of something which affects aliasing information, etc. All this isn't to say that the optimizer is wrong, your code likely still does have a bug, but it just explains the weird behaviour.
Debugging. It is very unlikely that the bug is in this line that is not reached. What I would focus on is setting watch points for the variables that are getting incorrect values (assuming you can narrow it down to what is receiving the wrong value).
These very weird issues often indicate an uninitialized variable or something along those lines. If the underlying compiler supports it, you can try providing an option that will cause the program to trap when an uninitialized memory location is being accessed.
Finally, this could be an indication that something is overwriting areas of the stack (and perhaps less likely other memory areas - heap, data). If you have anything that is writing to arrays allocated on the stack, check if you're walking past the end of the array.
Make sure you're using { and } around the bodies in your if() and else clauses. Without them it's easy to wind up with something like this:
if (a)
do_a_work();
if (b)
do_a_and_b_work();
else
do_not_a_work();
Which actually equates to this (and is not what's implied by the indenting):
if (a) {
do_a_work();
}
if (b) {
do_a_and_b_work();
} else {
do_not_a_work();
}
because the brace-less if (a) only takes the first statement below it for its body.
Commenting out your mystery line may be changing which code belongs to which if-else.

Throwing a logical error exception or just abort in a library?

I like very much the assert behaviour for testing invariants and pre-conditions in my code. I use it a lot. But now I am developing a library (C++) and I like the client (the programmer who uses the library) to know when he violates the precondition. I think is easier to see the application crashes and fix the problem than just throwing in a undefined behaviour.
I could just use assert in this situation, but when my library is ready a release build will disable the assert macro. I know I can keep it but I'm not sure I want to because there is a lot of internal asserts don't need being tested in release build.
An instance:
Some state machine has a maximum number of states that can be added. The limit is setted by the client in the constructor. Then, the client calls the method addState to add specific states, but of course, he can't add more states than he said initially.
Should I:
Just ignore states after the limit and, probably, start a state machine with undefined behaviour (at least to client perspective)?
Keep assertions alive and put an assertion at that point?
Throw an exception (some std::logic_error, I presume)?
Just print a message to stderr and abort the program?
I don't like 1. very much. The idea is tell the client what is he doing wrong.
Is this a situation to throw a logical error exception?
Is there another, better possibility?
Thanks.
Definitely, if a problem is "detectable", you should do something to inform the "user" of the error (some things are very hard to identify that it's gone wrong)
You use assert when the programmer does something directly wrong, and that is unlikely to happen in "normal use" of the code. E.g. if you have a pointer parameter that mustn't be NULL, doing assert(ptr != NULL) would be a sensible thing, likewise if you have an int that is a count of something, it probably shouldn't be negative (but then it should probably be unsigned?). These type of things don't necessarily need to be that clearly documented - just that the precondition "ptr must not be NULL" or "count should not be negative".
You use exceptions for something that MAY happen in normal running conditions, but really shouldn't. Such as running out of memory, or the "user" trying to add too many things to something that they had a reason to give a reasonable size in the first place. Exceptions should be clearly documented by the description of the function - "If you try to add more states than you have reserved space for, the exception x will be thrown".
I personally would think that a "custom" exception would make more sense than std::logic_error. In this case, perhaps too_many_states? The more distinct your exception is, the easier it is to determine where it came from and what it means. Nothing worse than getting some "generic" exception and not knowing how you ended up there - and when you search for it, there are hundreds of places it could have come from...

Alternative to exceptions for methods that return objects

I have a class that can perform many types of transformations to a given object.
All data is supplied by the users (via hand crafted command files) but for the most part there is no way to tell if the file commands are valid until we start transforming it (if we checked everything first we'd end up doing the same amount of work as the transformations themselves)
These transformation methods are called on the object and it returns a newly transformed object however if there is a problem we throw an exception since returning an object (even a blank object) could be confused with success whereas an exception sends a clear signal there was a problem and an object can not be returned. It also means we don't need to call a "get last error" type function to find out exactly what went wrong (error code, message, statement, etc.)
However from reading numerous answers on SO it seems this is incorrect since invalid user input is not an exceptional circumstance and due to the complexity of this thing its not uncommon for the user to submit incorrect command files.
Performance is not really an issue here because if we hit an error we have to stop and go back to the user.
If I use return codes I'd have to take the output object as a parameter and then to check the return codes I'd need long nested if blocks (ie. the way you check HRESULT from COM)
How would I go about avoiding exceptions in this case while still keeping the code reasonably tidy?
The design of your problem really lends itself for exceptions. The fact that program execution will halt or be invalid once the user supplies a bad input file, is a sign of "exceptional circumstance". Sure, a lot of program runs will end in an exception being thrown (and caught), but this is in one execution of the program.
The things you are reading about exceptions being slow when used for every other circumstance, is only valid if the program can recover, and has to recover often (e.g. a compiler that fails to find a header in a search directory, and has to look at the next directory in the list of search directories, which really happens a lot).
Use exceptions. When in doubt, measure if this is killing performance. Cleaner code >> following what people say on SO. But then again, that would be a reason to ignore what I just said.
Well, I wouldn't (avoid exceptions). If you really need an "error reporting" mechanism (and you do), there is not much besides return values and exceptions. I think the whole argument about what is exceptional enough (and therefor deserves exceptions) and what is not, is not that important to keep you from solving your problem. Especially if performace isn't an issue. But if you REALLY want avoid exceptions, you could use some kind of global queues to queue your error iformation. But that is utterly ugly, if you ask me.