Why check only certain values for errors? (C++?) - c++

I recently started learning DirectX/Windows, and the book I'm learning from had the code
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d == NULL)
//catch error &c.
My question is: What would cause an error in this line, that is different than what would cause an error in another line (say, for example, int num = 42)?

d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (d3d == NULL)
This is an error or not according to the meaning you give to the return value of Direct3DCreate9, i.e. depending on the specification of the function. I've written many pointer-returning functions for which NULL as a return value was not an erroneous situation.
So, do not equate "a function returning NULL" to "an error". An unambiguous error is a crash (technically, undefined behaviour) in your code, like if d3d is indeed NULL and later you dereference it.
int num = 42;
Here you are declaring an int variable called num and initializing it with a value of 42. What kind of error can you think of? Obviously, num will never "be NULL", if that bothers you. 42 may be a correct value or an error, depending on the context.

I think the comment is indicating that if Direct3DCreate9(D3D_SDK_VERSION); has returned NULL, then it is an error that should be handled.
From msdn:
IDirect3D9 * Direct3DCreate9( UINT
SDKVersion );
Parameters
SDKVersion
The value of this parameter should be D3D_SDK_VERSION. See Remarks.
Return Values
If successful, this function returns a
pointer to an IDirect3D9 interface;
otherwise, a NULL pointer is returned.
It is not saying that the comparison d3d == NULL might throw an exception.

It's important to catch that error because it's a show-stopper and because it can and does happen. As for other errors - I don't know what other errors you're talking about.
Certainly all errors should be checked for and handled. But remember that in a book, the priority is to make the key points as readable and understandable as possible. Complete error checking would get in the way of that, so it is often left as that infamous exercise for the reader.

Related

When NULL cannot be replaced by nullptr?

I am refactoring some older code that uses NULL in many places. The question is
Is it safe to blindly replace all NULL instances by nullptr?
I am particularly interested in scenario where replacing NULL by nullptr may lead to some run-time errors (compile-time errors would be ok) but I can't think of any. If not, would it be safe to just auto-replace NULL by nullptr (fixing compile time errors if any).
I apologize if question have been asked earlier - I couldn't find it, I will delete it if you point me to the answer!
In practice it should be fairly safe.
But, technically, it is possible that the meaning of your program changes, without causing any compiler errors. Consider the following program:
void foo(int) { std::cout << "int\n"; }
void foo(int*) { std::cout << "int*\n"; }
int main() {
foo(NULL); // prints 'int'
foo(nullptr); // prints 'int*'
return 0;
}
Note that when there's ambiguity between an int and a pointer when passing NULL, the pointer version is what's almost always desired -- which means that most real programs won't have an ambiguity like that in the first place (or will use casts like (int*)NULL to get around it, in which case replacement by nullptr is perfectly fine).

Strange Klocwork issues reported for C++ project

I am finding some of the issues reported by Klocwork is very strange. For example -
if(NULL == m_pMutex.get())
{
Log("found unexpected sharedPtr m_pMutex");
return -1;
}
Time_Critical_Section cs(*m_pMutex);
For the above code Klocwork reports NULL pointer dereference. But I don't think this is a valid issue. As if the pointer is null it would have returned from the function and wouldn't have a chance to access the pointer. But stil Klocwork reported this as an issue.
Another issue is-
char buf[1000];
sprintf(buf,"%s",name);
for the above code Klocwork says the above code portion can cause Buffer overflow, array index of 'buf' may be out of bounds. But we are confirming that the name variable will not be greater than 1000 bytes. But still Klocwork reported this as an issue.
We need to make our code error free, and the final code should not contain any issues for Klocwork. Could anyone suggest an efficient way to overcome the above issues?
Found the root cause of null pointer dereference issue. Let us explain why this code is getting null pointer dereference.
if(NULL == m_pMutex.get())
{
Log("found unexpected sharedPtr m_pMutex");
return -1;
}
Time_Critical_Section cs(*m_pMutex);
As Klocwork is a static code analyzer when it comes to check the pointer in "Time_Critical_Section cs(*m_pMutex);" it finds it in open block though it has been checked earlier and if the pointer is null we have returned from the function with value -1. When Klocwork is doing static code analysis it is unknown to it that it has earlier checked the pointer as the accessing code of pointer in open block. We can solve this problem by modifying the code in following way -
if(NULL == m_pMutex.get())
{
Log("found unexpected sharedPtr m_pMutex");
return -1;
}
else
{
Time_Critical_Section cs(*m_pMutex);
//Do some operations
return 0;
}

c++ check variable to address out of bounds

I use some function, and this function return variable of LPWSTR type (wchar_t*)
at debugger i look at this variable and see error "0x2e (Address 0x2e out of bounds)"
and when i do some operations with its variable, my program terminated.
I can't change called function, i haven't its src code.
my question is : Is c/c++ language have functions to check situation before call incorrect variable? i try try/catch block, but its not helped.
Excuse me for my english and thanks for any help
edited:
fragment of code with error
PCERT_EXTENSION pCe = CertFindExtension(szOID_CRL_DIST_POINTS, pCertInfo->cExtension, pCertInfo->rgExtension);
if (pCe) {
PCRL_DIST_POINTS_INFO pCrlDistPointsInfo = NULL;
PCRL_DIST_POINT *pCrlDistPointsPtr = NULL;
PCRL_DIST_POINT pCrlDistPoints = NULL;
DWORD pdwCrlDistPoints = sizeof (CRL_DIST_POINTS_INFO);
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
szOID_CRL_DIST_POINTS,
pCe->Value.pbData,
pCe->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
(PCRYPT_DECODE_PARA) NULL,
&pCrlDistPointsInfo,
&pdwCrlDistPoints)) {
printf("\n\nCannot decode CRL URL.\n\n");
}
if (pCrlDistPointsInfo) {
pCrlDistPointsPtr = (PCRL_DIST_POINT*) pCrlDistPointsInfo->rgDistPoint;
if (pCrlDistPointsPtr && pCrlDistPointsInfo->cDistPoint > 0) {
findCDP = true;
fwprintf(pFile, L"^^");
for (int i = 0; i < pCrlDistPointsInfo->cDistPoint; i++) {
pCrlDistPoints = &pCrlDistPointsInfo->rgDistPoint[i];
if (pCrlDistPoints) {
LPWSTR str = (LPWSTR) pCrlDistPoints->DistPointName._empty_union_.FullName.rgAltEntry->_empty_union_.pwszURL;
//printf("last error= 0x%08X", GetLastError());
fwprintf(pFile, str);//PROGRAM TERMINATED HERE!!!
fwprintf(pFile, L";");
}
printf("%d\n",i);
}
}
free(pCrlDistPointsInfo);
}
}
No, it doesn't have. If you set a pointer, which points to an invalid memory location, every access to the object at that location is an undefined behavior. What will most likely happen is a crash or some kind of memory corruption.
If a pointer has value 0x0000002e, it can mean only two things:
A bug in code which returns that. You're out of luck if you can't fix that...
An undefined pointer value, and reason for error is returned some other way, such as by modified reference parameter. But returning undefined value instead of null pointer would still count as a bug in my book.
On the other hand 0x2e sounds like ASCII character, '.' to be exact, so are you sure you are looking at pointer value instead of the string pointed to?
Late edit: looking at the code, it seems unions are involved. A possible reason for crash then is, you are accessing wrong member of union. In C union, all members/fields are in same memory location, they overlap. In other words, union can hold only one value at a time, and you need to know which one somehow, such as from documentation of function which initializes the union value, or by some extra variable which tells the type (common pattern in C is to have struct which contains type field and union field).
Windows has functions to check whether an address is a correct address or not. BUT... it's bad practice to rely on this, since there is no guarantee that if the pointer points to a correct address, that this is the address that you want.
The functions in windows are: IsBadReadPtr, IsBadWritePtr and IsBadCodePtr. I strongly suggest to only use these functions in debugging code (asserts e.g.) and never rely on this in a release executable.
If your application is designed and working correctly, you should never rely on these Windows functions.

Malloc error in std::string

I'm getting the error
malloc: *** error for object 0x101346a70: pointer being freed was not allocated
When using an std::string. Sometimes it occurs, sometimes it does not.
string1 += string2[i]
This is the statement which it breaks on (I've obviously changed the variable names)
I'm running Xcode 4.0.2 and using llvm.
I'm fairly certain that there isn't a bug with my code (although the error only occurs under a single function call). Is std::string even supposed to have errors like that?
Some googling returns this:
I haven't tried doing this however, as I use Macro's and the article is incredibly breif and not explanatory as to what macro causes this issue and why. I also found some other logs of mac developers complaining of similar errors, but have sofar found no other solutions.
Do I just have buggy code, or is this a problem with Xcode/LLVM/STL Implementation
-- Edit for source code and class explinations --
Explanations:
This function is for getting a c-string out of a class which is message,
primarily a string and some accompanied data. A printf style notation is used
for where the data should go in the message, ie %f means float.
MSIterator is just a typecast for an unsigned int.
I should point out that I wrote this a few years ago, so it doesn't have the best practises in terms
of naming and other practises.
Hopefully the variable names will be all thats needed to show what the variables are.
string MSMessage::getString()
{
string returnValue;
Uint stringElementIndex = 0;
Uint floatElementIndex = 0;
// Iterate through arguments
for(MSIterator messageIndex = 0; messageIndex < m_message.size();++messageIndex)
{
if(m_message[messageIndex] == '%')
{
// Check the next character
switch (m_message[++messageIndex])
{
case 's':
returnValue += string(m_stringArguments[stringElementIndex]);
++stringElementIndex;
break;
case 'f':
returnValue += StringServices::toString(m_floatArguments[floatElementIndex]);
++floatElementIndex;
break;
case '%':
returnValue+='%';
break;
default:
/* Otherwise, act as if its normal text */
returnValue+='%';
returnValue+=m_message[messageIndex];
break;
}
}
// Not a argument? Tack it on!
else
{
// Malloc Error is here, with one character in returnValue and another 50 or so in m_message,
// Message index is correctly equal to 1
returnValue += m_message[messageIndex];
}
}
return returnValue;
}
m_message is set to "The text object iterator given to GUITextLine::insertTextObject was not valid". ie, there is no
associated data, and no '%' characters to complicate things.
EDIT 2:
The function now returns an std::string (I've changed the source code as well), and still fails with the same error. I'm really confused.
EDIT 3:
This:
MSMessage x = MSMessage("The text object iterator given to
GUITextLine::insertTextObject was not valid", MSRegion_Systems,
MSZone_Object, MSType_Error_Orange, 0);
string y;
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
y = x.getString();
Doesn't seem to be causing any problems. Any thoughts?
returnValue is a local variable, so it automatically gets deleted when the function returns. This invalidates returnValue.c_str(). After returning to the calling function, the contents of the returned value will be undefined; and any attempt to free the pointer will corrupt the heap. This heap corruption may not be detected immediately; in fact it looks like it gets detected on a subsequent call of MSMessage::getCString().
Edited to add: As a quick fix, you can just change the last line to:
char* t = new char[returnValue.length() + 1] ;
strcpy (t, returnValue.c_str()) ;
return t ;
It is not good style to allocate something in a called function that must be freed by the calling function like this, but judging by your comment, it will save you a lot of work :-)
This kind of error is often caused by a memory corruption somewhere else in your program. The next call to one of the memory managment functions will then fail, because the heap is corrupt.
I believe the safest solution here would be to have the caller pass down the string that is currently declared as returnValue after having creating it using new(), have getString() (which might be better called stuffString()) stuff it and expect to caller to use it and free it using delete() when done with it. Any use of malloc() with a properly designed std class introduces un-necessary danger, since the class can only keep track of the storage it has allocated for itself and of course, that which was allocated by new(). I belive that once created, std:string should automatically allocate and track any space needed for any text added to it using its own methods and overloaded operators (if I'm being naive here, please correct me), so there should be no need to ever use malloc().
PS: The one exception I can see to this is the case where one wants to instantiate a C-style string with the contents of an existing std:string. Then one could write
char* new_C_string = malloc(strlen(old_CPP_string.c_str) + 1);
strcpy(new_c_string, old_CPP_string.c_str);
This would, of course, be a last resort to glue existing C code with existing C++ code. Tomas it right, this stuff can get very confusing.
return returnValue.c_str();
You may not do this. .c_str() necessarily returns a pointer to the string's internal storage, because there is no way to have it create a copy without there being a memory leak in general. (This is not C, where there is a culture of waving a magic documentation wand and thereafter freely expecting the caller to clean up the callee's messes.) Upon returning from the function, returnValue ceases to exist, and thus returnValue.c_str() is a dangling pointer, and any attempt to use it is undefined behaviour.
The normal way to approach the problem is to - drum roll - just return the string. Use the string class everywhere possible - why reject a real string type when you finally have it? The reason .c_str() is named that way is because it's for C interoperability. Accordingly, you use it at the point where actual interoperation with C code is required. For example, when passing the string to a C function.
Note that the C function may not legally modify the pointed-at data, because there is no way for the string object to know about the changes, so that would break the class invariants. If your C function requires a mutable char buffer, then you'll have to create one. One possible approach is to copy the characters into a std::vector<char> and pass a pointer to the internal storage of that. Of course, you still won't be able to capitalize on the vector's auto-resizing, because there is no way for the C code to interact with the vector's full interface. But then, most well-behaved C code doesn't assume it can "resize" strings "in-place" anyway. If you have something that expects a char** and the ability to replace the input "string", or something that attempts to realloc() a string, well... you may have to get a little creative, or better yet just abandon that C library.

Using "assert" with pointers in C++

When do we need to use "assert" for pointers in C++, and when they are used, how are they most commonly implemented?
Generally you would use an assert to check a condition that, if false, would indicate a bug in your application. So if a NULL pointer shouldn't ever be encountered at some point in the application, unless there's a bug, then assert it. If it might be encountered due to some invalid input then you need to do proper error handling.
You don't need to use assert on pointers at all. The idea is to ensure you don't crash when dereferencing your pointers when they're null.
You can do this with assert but it's not a very professional way to handle errors like this since it invariably terminates the program - not a good idea if the user hasn't, for example, saved their last three hours worth of data entry.
What you should do with pointers is to check them for null-ness and fail gracefully. In other words, have your function return an error of some sort or do nothing (not everyone will agree with this approach but it's perfectly acceptable if it's documented).
The assert stuff is meant, in my opinion, for catching problems during development which is why you'll find assert does nothing in release builds under some compilers. It is not a substitute for defensive programming.
As to how to do it:
#include <assert.h>
void doSomethingWithPointer (int *p) {
assert (p != 0);
cout << *p << endl;
}
but this would be better done as:
void doSomethingWithPointer (int *p) {
if (p != 0)
cout << *p << endl;
}
In other words, even if your "contract" (API) states that you're not allowed to receive null pointers, you should still handle them gracefully. An old quote: be conservative in what you give, liberal in what you accept (paraphrased).
ASSERT statements are great as "enforced documentation" - that is, they tell the reader something about the code ("This should never happen") and then enforces it by letting you know if they don't hold true.
If it's something that could happen (invalid input, memory not able to be allocated), that's not a time to use ASSERT. Asserts are only for things that can not possibly happen if everyone is obeying pre-conditions and such.
You can do it thusly:
ASSERT(pMyPointer);
From experience if you assert on null conditions that should never happen under normal conditions you program is in a really bad state. Recovering from such null condition will more likely than not mask the original problem.
Unless you code with exception guarantee in mind (linky) I say let it crash, then you know you have a problem.
I would use an ASSERT where a null pointer wouldn't immediately cause a crash but might lead to somethign wrong later that's hard to spot.
eg:
ASSERT(p);
strcpy(p, "hello");
Is a little unnecessary, it simply replaces a fatal exception with a fatal assert!
But in more complex code, particulalrly things like smart pointers, it might be useful to know check if the pointer is what you thing it is.
Remember ASSERTs only run in debug builds, they dissapear in the release.
In C, there also assert function..
in debug mode, if assert(x), x condition is false, there will pop up an alert...
But remember it works only in debug mode...
in release mode, all assert functions are all skipped
Assertions are used to to define how the program should function. That being said, the most common use of Assert()s when dealing with pointers is going to either be that they are valid (non-NULL and point towards valid memory) or that their internal state is valid if they point to an object/class instance, for example.
Assertions are not for replacing or acting as error condition code, but instead to enforce rules that you are placing on the functioning of your code, such as what conditions should be at given points in time.
For example,
function int f(int x, int * pY)
{
// These are entrance conditions expected in the function. It would be
// a BUG if this happened at all.
Assert(x >= 0);
Assert(pY != nullptr);
Assert(*pY >= 0, "*pY should never be less than zero");
// ...Do a bunch of computations with x and pY and return the result as z...
int z = x * 2 / (x + 1) + pow(*pY, x); // Maybe z should be always positive
// after these calculations:
Assert(x >= 0, "X should always be positive after calculations);
// Maybe *pY should always be non-zero after calculations
Assert(*pY != 0, "y should never be zero after computation");
Assert(z > 0):
return z;
}
Many users of Asserts choose to apply Assertions to internal state validation once they become familiar with them. We call these Invariants() which are methods on a class that assert many things about the internals of the object that should always hold true.
For example:
class A
{
public:
A(wchar_t * wszName)
{
_cch = 0;
_wszName = wszName;
}
// Invariant method to be called at times to verify that the
// internal state is consistent. This means here that the
// internal variable tracking the length of the string is
// matching the actual length of the string.
void Invariant()
{
Assert(pwszName != nullptr);
Assert(_cch == wcslen(pwszName));
}
void ProcessABunchOfThings()
{
...
}
protected:
int _cch;
wchar_t * pwszName;
}
// Call to validate internal state of object is consistent/ok
A a(L"Test Object");
a.Invariant();
a.ProcessABunchOfThings();
a.Invariant();
The important thing to remember is that this is to make sure that when bugs do happen that mean the program is not working as you would expect, then the effect of the bug happens as close to where it happened in the code as possible in order to make debugging easier. I have used Asserts extensively in my own code and while at Microsoft and I swear by them since they have saved me so much time in debugging and even knowing the defect is there.