I have a template 2D image buffer class that can be used with many values types. The values are stored as a 1D dynamic array of T
, accessed by a Row
method to get a pointer to the correct row.
One of the methods of the class is used to sample a value in the image bilinearly.
The code generally works, but ever so rarely I get an access violation exception in this method in production which I can't seem to recreate, because the crash dump doesn't include the coordinates that were passed to the method.
These are the relevant parts of the code:
T* data;
int width, height;
T* Row(int y) const { return data + width * y; }
T GetValueBilinear(float x, float y) const
{
const float PIXEL_CENTER_OFFSET = 0.5F;
const float cx = clamp(0.0F, width - 1.0F, x - PIXEL_CENTER_OFFSET);
const float cy = clamp(0.0F, height - 1.0F, y - PIXEL_CENTER_OFFSET);
const float tx = fmod(cx, 1.0F);
const float ty = fmod(cy, 1.0F);
const int xInt = (int)cx;
const int yInt = (int)cy;
const T* r0 = Row(yInt);
const T* r1 = ty && yInt < (height - 1) ? Row(yInt + 1) : r0;
//interpolate on Y
const T& c00 = r0[xInt];
const T& c01 = r1[xInt];
T c0 = lerp(c00, c01, ty);
if (tx && xInt < (width - 1))
{
//interpolate on X
const T& c10 = r0[xInt + 1];
const T& c11 = r1[xInt + 1];
T c1 = lerp(c10, c11, ty);
return lerp(c0, c1, tx);
}
else
{
return c0;
}
}
The definitions for clamp
, and lerp
are:
template <typename T>
inline T clamp(T min, T max, T value) { return value < min ? min : value > max ? max : value; }
template <typename T>
inline T lerp(T a, T b, float t) { return a + (b - a) * t; } //i.e. a(1-t)+bt
Do you see any obvious errors which would cause an access violation for any values of x
and y
which are not NaN?
You can assume that width
, height
and data
are valid and correct (i.e., positive dimensions - in this particular case 1280x720, data
is not dangling pointer).
If it matters, then T
is a float
in this case.
The fact that this is non-reproducible and generally working 99.9% of the time, makes me feel like it could be an accuracy issue, though I can't see where it would come from.
Alternatively, what debugging techniques could I use to analyze the crash dumps more effectively?