Debugging software that can check for NULL dereferences? - c++

Is there software smart enough to figure out that you got a pointer from somewhere and the returned pointer could be NULL and no where in the block do you do:
ptr = getSomeDataThatCouldReturnNULLAt(-1);
...
if(ptr)
{
//code
}
or
if(!ptr)
{
return;
}
Is there software that can let you know all the places where this might not be checked?
Thanks
Checking for runtime problems.

the better way to code this would be as follows :
s32 getSomeDataThatCouldReturnNULLAt( s32 intParam, void **inputPointer);
and then in your function where you want to invoke this function :
s32 returnValue = 0 ;
void * ptr = NULL ;
if((returnValue = getSomeDataThatCouldReturnNULLAt( -1, &ptr) ) != ERROR ||
ptr ==NULL )
return returnValue;
returnValue can indicate the error that occured in your getSomeDataThatCouldReturnNULLAt

Related

How can I use more memory?

I got the following error:
std::bad_array_new_length at memory location 0x00B3F9D8
It is because of this part:
U32 rayCountSqrt = (U32)(std::ceil(objWidthLambda * (T)(observation.rayPerLam_) + 1.0)) + 1;
rayPool.Initialize( rayCountSqrt);
And if we look at the Initilialize method
void Initialize( const U32& rayCountSqrt )
{
Reset();
rayCountSqrt_ = rayCountSqrt;
rayCount_ = rayCountSqrt * rayCountSqrt;
rayArea_ = 0;
rayTubeArray_.reset( new RayTube< T >[ rayCount_ ], []( RayTube< T >* ptr ){ delete[] ptr; } );
init_ = true;
}
Problem is probably located here, because when I pass for example 10 to Initialize I get no errors. My rayCountSqrt is 86354 and I don't know if it's too big to handle.
How can I fix this? I really need to pass large numbers to this function in order to get good approximations.

CString used on static method

I am stuck into a problem, and I will be very grateful if you help me.
I have a MDI, and in CDocument class, I have a struct:
CMyDoc.h
class CMyDoc : public CDocument
{
...
struct SRecord
{
SRecord(){}
virtual ~SRecord(){}
CString sName;
CString sState;
CString sDateu;
CString sDatec;
};
CTypedPtrArray<CPtrArray, SRecord*> m_arrRecord;
and somewhere I load this struct with data:
SRecord* pItem = new SRecord;
pItem->sName = saItem.GetAt(ML_ASSETNAME);
pItem->sState = saItem.GetAt(ML_STATE);
pItem->sDateu = saItem.GetAt(ML_DATEU;
pItem->sDatec = saItem.GetAt(ML_DATEC);
m_arrRecord.Add(pItem);
ok. I am trying to sort data:
void CMyDoc::SortData(int nColumn, BOOL bAscending)
{
switch(nColumn)
{
case 9:
if(bAscending)qsort((void*)m_arrRecord.GetData(), m_arrRecord.GetSize(), sizeof(SRecord), CompareDateUAscending);
else qsort((void*)m_arrRecord.GetData(), m_arrRecord.GetSize(), sizeof(SRecord), CompareDateUDescending);
break;
...
}
but the problem become when data is access in static method:
int CMyDoc::CompareDateUDescending(const void* arg1, const void* arg2)
{
SRecord* Record1 = (SRecord*)arg1;
SRecord* Record2 = (SRecord*)arg2;
if(Record1->sDateu.IsEmpty() || Record2->sDateu.IsEmpty()) // <--- crash !
return 0;
COleDateTime dL, dR;
dL.ParseDateTime(Record1->sDateu);
dR.ParseDateTime(Record2->sDateu);
return (dL == dR ? 0 : (dL < dR ? 1 : -1));
}
and the crash take me here (atlsimpstr.h):
CStringData* GetData() const throw()
{
return( reinterpret_cast< CStringData* >( m_pszData )-1 ); // the crash lead me on this line
}
what I am doing wrong ?
Any help will be very appreciated !
Update:
I have tried this:
int CMyDoc::CompareDateUDescending(const void* arg1, const void* arg2)
{
SRecord* Record1 = *(SRecord**)arg1; // <-- OK
SRecord* Record2 = *(SRecord**)arg2; // <-- Unhandled exception* see note below
if(Record1->sDateu.IsEmpty() || Record2->sDateu.IsEmpty())
return 0;
COleDateTime dL, dR;
dL.ParseDateTime(Record1->sDateu);
dR.ParseDateTime(Record2->sDateu);
return (dL == dR ? 0 : (dL < dR ? 1 : -1));
}
and the crash told me:
"An unhandled exception was encountered during a user callback." strange ...
The qsort comparison function receives pointers to the elements in the array. But since the elements in the array are themselves pointers what your specific function receives as arguments are pointers to pointers to SRecord, i.e. SRecord**.
You can solve it by doing e.g.
const SRecord* Record1 = *reinterpret_cast<const SRecord**>(arg1);
That is, you cast arg1 to SRecord** and then dereference that pointer to get a SRecord*.
Example on how to use the C++ standard sort function.
First you need to update your comparison function a little:
// The comparison function should return true if Record1 is *smaller* than Record2,
// and return false otherwise
bool CMyDoc::CompareDateUDescending(const SRecord* Record1, const SRecord* Record2)
{
return Record1->sDateu < Record2->sDateu;
}
Then to call sort:
std::sort(m_arrRecord.GetData(), m_arrRecord.GetData() + m_arrRecord.GetSize(), CompareDateUDescending);
Much simpler!

Bool assignment operator

I have a method where I create objects on the heap and return a boolean which indicates if it went well or not.
I am not 100% sure about my bool assignments though in (1); is this legal to do?
bool ret = true;
if (ret = !mRenderBackend) // make sure mRenderBackend is NULL
{
if (mEngineSettings.GetRenderBackend() == OPENGL)
ret = mRenderBackend = mMemoryAllocator.AllocateObject<RenderOpenGL>(); // (1). AllocateObject returns either NULL or object address
}
return ret;
Thanks
You don't really need the bool at all, it sort of makes it harder to follow. I would personally do something like,
if (mRenderBackend == NULL) // make sure mRenderBackend is NULL
{
if (mEngineSettings.GetRenderBackend() == OPENGL)
mRenderBackend = mMemoryAllocator.AllocateObject<RenderOpenGL>(); // (1). AllocateObject returns either NULL or object address
}
return (mRenderBackend != NULL);
Yes, legal.
if (ret = !mRenderBackend)
is equivalent to
ret = !mRenderBackend;
if(ret)
is equivalent to
ret = (mRenderBackend == 0);
if(ret)
Just note that ret will only be defined up to zero/nonzeroness which looks safe in your code.

Template Class Type Sizing

I have written a template class for a circular buffer:
template <class T> class CRingBuffer { /* ... */ };
Some of the operations this class performs rely on an accurate evaluation of the size of T. This seems to work okay when T is BYTE (i.e. sizeof(T) == 1, check). However, when I try to use the same class where T is DWORD, for some reason sizeof(T) evaluates to 16. The last time I checked, a double-word is 4 bytes, not 16. Does anyone know why this is happening? Thanks.
ADDITIONAL INFO
I can't post all the code due to its proprietary nature, but here is the class declaration and the function definition in question:
template <class T> class CRingBuffer
{
#pragma pack( push , 1 ) // align on a 1-byte boundary
typedef struct BUFFER_FLAGS_tag
{
T * pHead; // Points to next buffer location to write
T * pTail; // Points to next buffer location to read
BOOL blFull; // Indicates whether buffer is full.
BOOL blEmpty; // Indicates whether buffer is empty.
BOOL blOverrun; // Indicates buffer overrun.
BOOL blUnderrun; // Indicates buffer underrun.
DWORD dwItemCount; // Buffer item count.
} BUFFER_FLAGS, *LPBUFFER_FLAGS;
#pragma pack( pop ) // end 1-byte boundary alignment
// Private member variable declarations
private:
T * m_pBuffer; // Buffer location in system memory
T * m_pStart; // Buffer start location in system memory
T * m_pEnd; // Buffer end location in system memory
BUFFER_FLAGS m_tFlags; // Buffer flags.
DWORD m_dwCapacity; // The buffer capacity.
// CRingBuffer
public:
CRingBuffer( DWORD items = DEFAULT_BUF_SIZE );
~CRingBuffer();
// Public member function declarations
public:
DWORD Add( T * pItems, DWORD num = 1, LPDWORD pAdded = NULL );
DWORD Peek( T * pBuf, DWORD num = -1, DWORD offset = 0, LPDWORD pWritten = NULL );
DWORD Delete( DWORD num, LPDWORD pDeleted = NULL );
DWORD Remove( T * pBuf, DWORD num = 1, LPDWORD pRemoved = NULL );
void Flush( void );
DWORD GetItemCount( void );
BYTE GetErrorStatus( void );
// Private member function declarations
private:
void IncrementHead( LPBUFFER_FLAGS pFlags = NULL );
void IncrementTail( LPBUFFER_FLAGS pFlags = NULL );
};
template <class T> void CRingBuffer<T>::IncrementHead( LPBUFFER_FLAGS pFlags )
{
ASSERT(this->m_pBuffer != NULL);
ASSERT(this->m_pStart != NULL);
ASSERT(this->m_pEnd != NULL);
ASSERT(this->m_tFlags.pHead != NULL);
ASSERT(this->m_tFlags.pTail != NULL);
pFlags = ( pFlags == NULL ) ? &(this->m_tFlags) : pFlags;
// Verify overrun condition is not set.
if ( pFlags->blOverrun == FALSE )
{
pFlags->pHead += sizeof(T); // increament buffer head pointer
pFlags->blUnderrun = FALSE; // clear underrun condition
// Correct for wrap condition.
if ( pFlags->pHead == this->m_pEnd )
{
pFlags->pHead = this->m_pStart;
}
// Check for overrun.
if ( pFlags->pHead == pFlags->pTail )
{
pFlags->blOverrun = TRUE;
}
}
}
The problem described above occurs when pFlags->pHead += sizeof(T); of IncrementHead is executed.
Oh, this is really simple after all :)
Without realising it, in pFlags->pHead += sizeof(T); you use pointer arithmetic. pHead is a pointer to T, and when you increase it by sizeof(T), it means you move it forward by that many elements of type T, and not by that many bytes as you thought. So the size of T gets squared. If your goal is to move the pointer to the next element of the buffer, you should just increment it by 1: pFlags->pHead += 1;

faster than Stackwalk

Does anybody know of a better/ faster way to get the call stack than "StackWalk"?
I also think that stackwalk can also be slower on methods with a lot of variables...
(I wonder what commercial profilers do?)
I'm using C++ on windows. :)
thanks :)
I don't know if it's faster, and it won't show you any symbols, and I'm sure you can do better than that, but this is some code I wrote a while back when I needed this info (only works for Windows):
struct CallStackItem
{
void* pc;
CallStackItem* next;
CallStackItem()
{
pc = NULL;
next = NULL;
}
};
typedef void* CallStackHandle;
CallStackHandle CreateCurrentCallStack(int nLevels)
{
void** ppCurrent = NULL;
// Get the current saved stack pointer (saved by the compiler on the function prefix).
__asm { mov ppCurrent, ebp };
// Don't limit if nLevels is not positive
if (nLevels <= 0)
nLevels = 1000000;
// ebp points to the old call stack, where the first two items look like this:
// ebp -> [0] Previous ebp
// [1] previous program counter
CallStackItem* pResult = new CallStackItem;
CallStackItem* pCurItem = pResult;
int nCurLevel = 0;
// We need to read two pointers from the stack
int nRequiredMemorySize = sizeof(void*) * 2;
while (nCurLevel < nLevels && ppCurrent && !IsBadReadPtr(ppCurrent, nRequiredMemorySize))
{
// Keep the previous program counter (where the function will return to)
pCurItem->pc = ppCurrent[1];
pCurItem->next = new CallStackItem;
// Go the the previously kept ebp
ppCurrent = (void**)*ppCurrent;
pCurItem = pCurItem->next;
++nCurLevel;
}
return pResult;
}
void PrintCallStack(CallStackHandle hCallStack)
{
CallStackItem* pCurItem = (CallStackItem*)hCallStack;
printf("----- Call stack start -----\n");
while (pCurItem)
{
printf("0x%08x\n", pCurItem->pc);
pCurItem = pCurItem->next;
}
printf("----- Call stack end -----\n");
}
void ReleaseCallStack(CallStackHandle hCallStack)
{
CallStackItem* pCurItem = (CallStackItem*)hCallStack;
CallStackItem* pPrevItem;
while (pCurItem)
{
pPrevItem = pCurItem;
pCurItem = pCurItem->next;
delete pPrevItem;
}
}
I use Jochen Kalmbachs StackWalker.
I speedet it up this way:
The most time is lost in looking for the PDB files in the default directories and PDB Servers.
I use only one PDB path and implemented a white list for the images I want to get resolved (no need for me to look for user32.pdb)
Sometimes I dont need to dive to the bottom, so I defined a max deep
code changes:
BOOL StackWalker::LoadModules()
{
...
// comment this line out and replace to your pdb path
// BOOL bRet = this->m_sw->Init(szSymPath);
BOOL bRet = this->m_sw->Init(<my pdb path>);
...
}
BOOL StackWalker::ShowCallstack(int iMaxDeep /* new parameter */ ... )
{
...
// define a maximal deep
// for (frameNum = 0; ; ++frameNum )
for (frameNum = 0; frameNum < iMaxDeep; ++frameNum )
{
...
}
}
Check out http://msdn.microsoft.com/en-us/library/bb204633%28VS.85%29.aspx - this is "CaptureStackBackTrace", although it's called as "RtlCaptureStackBackTrace".