Forum: Mikrocontroller und Digitale Elektronik GCC ARM 2016q1, Ergebnis von Deklarationsreihenfolge abhängig


von Vincent H. (vinci)


Lesenswert?

Grüß euch

Ich benötige für eine Kurvenglättung eine Interpolationsmethode und habe 
aus diesem Grund eine kurze Funktion geschrieben, die kubische Splines 
erzeugt.

Die Ergebnisse der Funktion bestehen aus den drei Koeffizienten der 
Splines und werden in eine Struktur gepackt.
1
struct Spline
2
{
3
  float a3;
4
  float a2;
5
  float a1;
6
};


Nun habe ich folgendes Problem. Aus irgendeinem Grund hängt das 
Rechenergebnis der Interpolation von der Reihenfolge ab mit der ich die 
Variablen vor dem Funktionsaufruf anlege.

Und zwar rechnen folgende Zeilen richtig:
1
int32_t start;
2
int32_t high;
3
int32_t mid;
4
Spline spline_cubic[3] = {};
5
float x[4] = {0.1, 1.3, 1.9, 2.1};
6
float y[4] = {1.3, 1.5, 1.7, 2.1};
7
uint32_t n = 4;
8
9
splineCubicSet(x, y, n, spline_cubic);

Und folgende Zeilen falsch?
1
int32_t start;
2
int32_t high;
3
int32_t mid;
4
float x[4] = {0.1, 1.3, 1.9, 2.1};
5
float y[4] = {1.3, 1.5, 1.7, 2.1};
6
uint32_t n = 4;
7
Spline spline_cubic[3] = {};
8
9
splineCubicSet(x, y, n, spline_cubic);


Hat jemand ev. eine Idee woran das liegen könnte?

von Jim M. (turboj)


Lesenswert?

Außer Stack Overflow würde mir da ertmal nix zu einfallen.
Zeige mal den vollständigen Code, da ist zu 99.99% was anderes faul.

von nicht"Gast" (Gast)


Lesenswert?

Moin,

Initialisiere deine Deklarationen mal vernünftig.

Sieht mir danach aus, als wenn du nicht initialisierte Variablen 
benutzt. Das würde auch dein Fehlerbild erklären.

von Vincent H. (vinci)


Lesenswert?

Jim M. schrieb:
> Außer Stack Overflow würde mir da ertmal nix zu einfallen.
> Zeige mal den vollständigen Code, da ist zu 99.99% was anderes faul.


Achtung die Funktion nutzt "variable length" arrays. Ich mach mich grad 
ran nochmal die leider recht komplexen Indizes zu prüfen...

Uninitialisierte Variablen seh ich keine.

1
__STATIC_INLINE void splineCubicSet(float x[], float y[], uint32_t n, Spline spline[])
2
{
3
  float h[n-1] = {};
4
  float u[n-2] = {};
5
  float z[n-2] = {};
6
7
  float tmp[2];
8
  uint32_t i;
9
10
  /* Do the fist one "by hand */
11
  h[0] = x[1] - x[0];
12
  h[1] = x[2] - x[1];
13
  tmp[0] = 2 * (x[2] - x[0]);
14
  u[0] = h[1] / tmp[0];
15
  tmp[1] = (3 / h[1]) * (y[2] - y[1]) - (3 / h[0]) * (y[1] - y[0]);
16
  z[0] = tmp[1] / tmp[0];
17
18
  /* Iterate others */
19
  for (i = 2; i < (n - 1); i++)
20
  {
21
    h[i] = x[i + 1] - x[i];
22
    tmp[0] = (2 * (x[i + 1] - x[i - 1])) - h[i - 1] * u[i - 2];
23
    u[i - 1] = h[i] / tmp[0];
24
    tmp[1] = (3 / h[i]) * (y[i + 1] - y[i])
25
        - (3 / h[i - 1]) * (y[i] - y[i - 1]);
26
    z[i - 1] = (tmp[1] - h[i - 1] * z[i - 2]) / tmp[0];
27
  }
28
29
  /* Do the last one "by hand */
30
  spline[n - 2].a2 = z[n - 3];
31
  spline[n - 2].a1 = (y[n - 1] - y[n - 2]) / h[n - 2]
32
      - (h[n - 2] * 2 * spline[n - 2].a2) / 3;
33
  spline[n - 2].a3 = -spline[n - 2].a2 / (3 * h[n - 2]);
34
35
  /* Iterate others */
36
  for (i = n - 2; i >= 1; i--)
37
  {
38
    spline[i].a2 = z[i - 1] - u[i - 1] * spline[i + 1].a2;
39
    spline[i].a1 = (y[i + 1] - y[i]) / h[i]
40
        - (h[i] * (spline[i + 1].a2 + 2 * spline[i].a2)) / 3;
41
    spline[i].a3 = (spline[i + 1].a2 - spline[i].a2) / (3 * h[i]);
42
  }
43
44
  /* Do the fist one "by hand */
45
  spline[0].a2 = 0;
46
  spline[0].a1 = (y[1] - y[0]) / h[0]
47
      - (h[0] * (spline[1].a2 + 2 * spline[0].a2)) / 3;
48
  spline[0].a3 = (spline[1].a2 - spline[0].a2) / (3 * h[0]);
49
}

von Dr. Sommer (Gast)


Lesenswert?

1
  /* Iterate others */
2
  for (i = n - 2; i >= 1; i--)
3
  {
4
    spline[i].a2 = z[i - 1] - u[i - 1] * spline[i + 1].a2;

Wenn i=n-2 ist, ist für n=4 also i=2. Somit ist i+1=3, und spline[i+1] 
ist ein Buffer Overflow, da spline nur 3 Elemente groß ist.

Und wieder einmal ist der Programmierer, und nicht der Compiler, schuld 
:P

von Vincent H. (vinci)


Lesenswert?

Dr. Sommer schrieb:
>
1
>   /* Iterate others */
2
>   for (i = n - 2; i >= 1; i--)
3
>   {
4
>     spline[i].a2 = z[i - 1] - u[i - 1] * spline[i + 1].a2;
5
>
>
> Wenn i=n-2 ist, ist für n=4 also i=2. Somit ist i+1=3, und spline[i+1]
> ist ein Buffer Overflow, da spline nur 3 Elemente groß ist.
>
> Und wieder einmal ist der Programmierer, und nicht der Compiler, schuld
> :P


Ah Gott sei Dank!!!
Ja dass der Programmierer Schuld ist war eh klar :)

Ich hab den Algorithmus zuerst in MATLAB runtergeschrieben, dass ja bei 
Indizes 1 zu zählen beginnt. Und als ob das nicht mühsam genug wär 
kommen einige temporäre Variablen dann halt auch noch entweder N-1 oder 
N-2 mal vor... was die Sache mit den Indizes nicht unbedingt 
vereinfacht. :)

Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.