Ich habe eine Vorlage 2D-Bildpufferklasse, die mit vielen Werttypen verwendet werden kann. Die Werte werden als dynamisches 1D-Array von T
gespeichert, auf das über eine -Methode zugegriffen wird, um einen Zeiger auf die richtige Zeile zu erhalten.Bilineare Bildabtastung Nicht reproduzierbare Zugriffsverletzung
Eine der Methoden der Klasse wird verwendet, um einen Wert im Bild bilinear abzutasten.
Der Code funktioniert im Allgemeinen, aber immer seltener bekomme ich eine Zugriffsverletzung Ausnahme in dieser Methode in der Produktion, die ich nicht neu erstellen kann, da der Absturz nicht die Koordinaten enthält, die an die Methode übergeben wurden.
Dies sind die relevanten Teile des Codes:
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;
}
}
Die Definitionen für clamp
und lerp
sind:
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
Haben Sie offensichtliche Fehler zu sehen, die eine Zugriffsverletzung für jede verursachen würde Werte von x
und y
, die nicht NaN sind?
können Sie davon ausgehen, dass width
, height
und data
sind gültig und richtig (das heißt, positive Dimensionen - in diesem speziellen Fall 1280x720 wird data
baumelt Zeiger nicht). Wenn es darauf ankommt, dann ist T
in diesem Fall ein float
.
Die Tatsache, dass dies nicht reproduzierbar ist und im Allgemeinen 99,9% der Zeit funktioniert, lässt mich glauben, dass es ein Genauigkeitsproblem sein könnte, obwohl ich nicht sehen kann, woher es kommen würde.
Oder, welche Debugging-Techniken könnte ich verwenden, um die Crash-Dumps effektiver zu analysieren?
Kann 'xInt' negativ sein? –
@AlessandroJacopson Ich sehe nicht, wie wenn 'cx' an' 0.0f' geklammert wird. – Rotem
Kann die Breite oder Höhe kleiner als 1 sein? Was ist das Verhalten von 'Row (yInt)'? Später greifen Sie auf das zurückgegebene 'r0' mit' xInt + 1' zu. Es gibt einfach nicht genug Details hier.Sie müssen einen Debugger durchlaufen, um die Werte Ihrer Indizes und die Größe Ihrer Arrays zu sehen. – AndyG