corrupted Stack bei Sortierverfahren

Von: , Frage gestellt am Di, 15. Dez 2009

Hallo,

ich programmiere eine Zeit schon an einem Programm, welches Bubble- und Mergesort vergleicht. Dazu erzeuge ich mehrere Arrays, die mit Zufallszahlen befüllt werden, und anschließend einmal mit Bubble und dann mit Merge sortiert werden. Darum herum wird die Zeit gemessen und am Ende ausgegeben, wie lange welches Sortierverfahren benötigt hat, bzw in welchen Verhältnis der Programmaufwand besteht.

Nun ist es so, dass ich immer eine Fehlermeldung erhalte:

"C Run-Time Check Failure #2 - Stack around the variable 'f' was corrupted."

Das ist mein letztes, zu sortierende Array für den Mergesort.
Wenn ich dieses auf 1000 Felder verkleinere, wie in dem Teil davor, bekomme ich die gleiche Fehlermeldung, allerdings für das Array 'd', also das Merge-Array von der Sortierung mit 1000 Feldern.

Also muss ich in einer Mergefunktion einen stackoverflow haben, nicht wahr? Ich finde aber meinen Fehler nicht. Um Hilfe wäre ich sehr dankbar!

mit Gruße,
Streuselchen

Der Code (das Hauptprogramm "main" ist ganz unten)

#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
void dreieckstausch(int *x, int *y)
{
int help;
help = *x;
*x = *y;
*y = help;
}
void bubble(int a[],int n)
{
int i,j;
for (i=0; i<(n-1); i++) //Durchlauf des gesamten Arrays
{
for(j=0; j<(n-1); j++) //sortierender Durchlauf
{
if(a[j]>a[j+1]) dreieckstausch(&a[j],&a[j+1]);
}
}
}
void merge(int a[], int low, int high, int mitte) //Zusammenfügen mit Hilfsarray c
{
int i,j,k, b[5000];
i=0;
j=low;
//erste Hälfte des Arrays a ins Hilfsarray b
while (j<=mitte)
b[i++]=a[j++];
i=0; k=low;
//Zurückkopieren des nächst größeren Elements
while (k<j && j<=high)
{
if (b[i] <= a[j]) a[k++] = b[i++];
else a[k++]=a[j++];
}
//Rückkopierung gemerkter Elemente der ersten Hälfte (wenn vorhanden)
while (k<j)
a[k++]=b[i++];
}
int mergesort(int a[], int low, int high)
{
int m; //Mitte des Arrays
if(low<high) //Rekursive Teilung des Arrays: "divide-and-conquer" 
{ //divide: Teilung bis nur noch ein Element vorhanden ist
m=(low+high)/2; //dazu wird das Array in zwei Arrays geteilt: 1.Array[Untergrenze...m], 2.Array[m+1...Obergrenze]
mergesort(a,low,m);
mergesort(a,m+1,high);
merge(a,low,high,m); //conquer: die Einzelteile werden schrittweise zusammengefügt
}
return(0);
}
double Zeitmessung(int *a, char* verfahren, int arraylaenge)
{
LARGE_INTEGER iFreq, iBegin, iEnd; //Var für Stoppuhr
double benötigteZeit; //Returnwert
if ((strcmp(verfahren, "bubble")) == 0) //Stoppuhr Bubble
{
QueryPerformanceFrequency(&iFreq); // Counterfrequenz, zählt pro Ticks/Sekunde
QueryPerformanceCounter(&iBegin); // Anzahl der Ticks seit PC-Start
bubble(a,arraylaenge);
QueryPerformanceCounter(&iEnd); // Anzahl der Ticks seit PC-Start + Funktionsberrechnung  
benötigteZeit=(double)(iEnd.QuadPart-iBegin.QuadPart)/iFreq.QuadPart;
}
else //Stoppuhr Merge
{
QueryPerformanceFrequency(&iFreq); 
QueryPerformanceCounter(&iBegin); 
mergesort(a, 0, arraylaenge);
QueryPerformanceCounter(&iEnd);
benötigteZeit=(double)(iEnd.QuadPart-iBegin.QuadPart)/iFreq.QuadPart;
}
return benötigteZeit;
}
void ZufallszahlenErzeugen(int *a,int n) //mit x=(a * x + c) % m, 0 <= x < m
{
int i=0;
srand(time(0)); // Intialisierung der srand Funktion; x=time(0)=Systemzeit
for (i = 0; i <= n; i++) {a[i] = rand()%20;} //%xy max Zahlenwert
}
int main()
{
double zeitB, zeitM;
int i=0, a[10], b[10], c[1000], d[1000], e[5000], f[5000];
char bubble[7]="bubble", merge[6]="merge";
////////////////////////////////Sortierung von 10 Zahlen///////////////////////////////////////////////
ZufallszahlenErzeugen(&a[0],9); //Erzeugung von Zufallszahlen + befüllen des Arrays
printf("Array mit Zufallszahlen:\n"); //Ausgabe des Zufallsarrays
for (i = 0; i <= 9; i++){printf(" %i " , a [i]);}
i=0;while(i<=10){b[i]=a[i];i++;} 
printf("\n\n\nmit einem Array von 10 Feldern:\n");
zeitB = Zeitmessung(a, &bubble[0], 10); //Berrechnung und Laufzeitmessung Bubblesort
zeitM = Zeitmessung(&b[0], &merge[0], 10); // "   Mergesort
for (i = 0; i <= 9; i++){printf(" %i " , a [i]);} //Ausgabe des sortierten Arrays (zum Vergleich)
printf("\n\n\nbenötigte Zeit Bubble: %4.7f sek\n",zeitB); //Ausgabe Laufzeit Bubblesort
printf("benötigte Zeit Merge : %4.7f sek\n",zeitM); //Ausgabe Laufzeit Mergesort
printf("\nZeitdifferenz: %4.7f sek",(zeitB-zeitM)); //Ausgabe Zeitdifferenz/Aufwand
printf("\nVerhältnis: %4.3f", zeitB/zeitM); //Ausgabe Verhältnis 
////////////////////////////////Sortierung von 1000 Zahlen///////////////////////////////////////////////
printf("\n\n\nmit einem Array von 1000Feldern:");
ZufallszahlenErzeugen(&c[0],999);
i=0;while(i<=1000){d[i]=c[i];i++;} 
zeitB = Zeitmessung(&c[0], bubble, 1000); //Berrechnung und Laufzeitmessung Bubblesort
zeitM = Zeitmessung(&d[0], merge, 1000); // "   Mergesort
printf("\nbenötigte Zeit Bubble: %4.7f sek\n",zeitB); //Ausgabe Laufzeit Bubblesort
printf("benötigte Zeit Merge : %4.7f sek\n",zeitM); //Ausgabe Laufzeit Mergesort
printf("\nZeitdifferenz: %4.7f sek",(zeitB-zeitM)); //Ausgabe Zeitdifferenz/Aufwand
printf("\nVerhältnis: %4.3f", zeitB/zeitM); //Ausgabe Verhältnis
////////////////////////////////Sortierung von 5000 Zahlen///////////////////////////////////////////////
printf("\n\n\nmit einem Array von 5000Feldern:");
ZufallszahlenErzeugen(&e[0],4999);
i=0;while(i<=5000){f[i]=e[i];i++;} 
zeitB = Zeitmessung(&e[0], &bubble[0],5000); //Berrechnung und Laufzeitmessung Bubblesort
zeitM = Zeitmessung(&f[0], &merge[0],5000); // "   Mergesort
printf("\nbenötigte Zeit Bubble: %4.7f sek\n",zeitB); //Ausgabe Laufzeit Bubblesort
printf("benötigte Zeit Merge : %4.7f sek\n",zeitM); //Ausgabe Laufzeit Mergesort
printf("\nZeitdifferenz: %4.7f sek",(zeitB-zeitM)); //Ausgabe Laufzeit Zeitdifferenz/Aufwand
printf("\nVerhältnis: %4.3f", zeitB/zeitM); //Ausgabe Verhältnis
getch();
return 0;
}



[MOD: code-tags in pre-tags umgewandelt]

3 Antworten zu dieser Frage

  1. Antwort von nach einer Stunde 0 hilfreich
    Re: corrupted Stack bei Sortierverfahren

    Hallo, Nun ist es so, dass ich immer eine Fehlermeldung erhalte:

    "C Run-Time Check Failure #2 - Stack around the variable 'f'
    was corrupted."
    An dieser Stelle solltest du deinen Debugger nach dem Stacktrace fragen. Wenn der Stack nicht allzu kaputt ist, solltest du herausfinden konnen, in welcher Funktion, von wo aus sie aufgerufen wurde etc. Das ist mein letztes, zu sortierende Array für den Mergesort.
    Wenn ich dieses auf 1000 Felder verkleinere, wie in dem Teil
    davor, bekomme ich die gleiche Fehlermeldung, allerdings für
    das Array 'd', also das Merge-Array von der Sortierung mit
    1000 Feldern.

    Also muss ich in einer Mergefunktion einen stackoverflow
    haben, nicht wahr? Ich finde aber meinen Fehler nicht. Um
    Hilfe wäre ich sehr dankbar!
    Das erste, was du tun kannst, ist das Problem zu reduzieren.

    Tritt der Fehler auch auf, wenn du keine Zeiterfassung aussen drum herum programmierst, sondern direkt die Sortierroutine aufrufst?

    Zweitens sind mir ein paar "magische" Konstanten aufgefallen:

    int i,j,k, b[5000];
    

    Sowas ist eigentlich fast immer eine schlechte Idee. Wenn du Performance messen willst, solltest du nicht einfach mal 5000 Elemente auf dem Stack allokieren, ausser der Algorithmus braucht unbedingt 5000. Waere mir aber bei mergesort neu

    Drittens hast du vermutlich implizite Annahmen in deinem Code, vielleicht sowas wie dass in merge(int a[], int low, int high, int mitte) die Ungleichungen
    low <= mitte && mitte <= high gelten, oder so aehnlich.

    Solche Annahmen solltest du explizit mit assert() schreiben, sodass du frueh mitbekommst wenn eine dieser Annahmen verletzt wird.

    Gruesse,
    Moritz

    • Antwort von nach 5 Stunden 0 hilfreich
      Re^2: corrupted Stack bei Sortierverfahren

      Hallo,
      ich danke erstmal dem Mod, der den Quellcode leserlich gestaltet hat.

      Ich habe nun weiter gewerkelt und einzelne Programmteile Schritt für Schritt in ein neues Programm kopiert. Dabei habe ich auch berücksichtigt, die Zeitmessung und das Erzeugen des Zufallsarrays auszusparen.

      So ist mir auch der Fehler aufgefallen, bzw ein Fehler (denn nun bekomme ich keine Fehlermeldung mehr):
      Den Funktionen Mergesort/Bubble werden die Längen der zu bearbeitenden Felder übergeben. Dabei habe ich die Zahl der Felder angegeben, nicht aber bedacht, dass ein Array mit der 0ten Stelle zu zählen beginnt. Also musste man alle Angaben der Arraylänge um 1 subtrahieren - schon ist der Stack nicht überfüllt.

      zum Beispiel:

      printf("\n\n\nmit einem Array von 10 Feldern:\n");
      zeitB = Zeitmessung(a, &bubble[0], 9); 
      
      An dieser Stelle solltest du deinen Debugger nach dem
      Stacktrace fragen. Wenn der Stack nicht allzu kaputt ist,
      solltest du herausfinden konnen, in welcher Funktion, von wo
      aus sie aufgerufen wurde etc.
      Aus Interesse:
      wie komme ich in C an den Stacktrace? Zweitens sind mir ein paar "magische" Konstanten aufgefallen:
      int i,j,k, b[5000];
      

      i, j, k sind ja nur Zeiger, um das Array abzutasten.
      b stellt ein Hilfsarray dar, mH dessen die zu sortierenden Mergeteile in die richtige Reihenfolge gebracht werden. Da b in meiner Programmierung nur halb so groß ist, wie das ursprungsarray, könnte ich es auf 2500 Felder reduzieren.
      Aber noch mehr?
      In meinem dritten Fall, also einer Sortierung von 5000 Zahlen, brauche ich doch ebenso viel Platz (bzw 2500 Felder) in dem Hilfsarray, oder?


      Aber auf jedenfall großen Dank dir!

      Streuselchen

      • Antwort von nach 5 Stunden 0 hilfreich
        Re^3: corrupted Stack bei Sortierverfahren

        Hallo, ich danke erstmal dem Mod, der den Quellcode leserlich
        gestaltet hat.
        bitteschoen. An dieser Stelle solltest du deinen Debugger nach dem
        Stacktrace fragen. Wenn der Stack nicht allzu kaputt ist,
        solltest du herausfinden konnen, in welcher Funktion, von wo
        aus sie aufgerufen wurde etc.
        Aus Interesse:
        wie komme ich in C an den Stacktrace?
        Mit dem Debugger, oder ansonsten abhaengig vom Betriebssystem.
        Ich kenne mich mit Windows nicht aus, aber hier scheint es ein paar gute Links zu geben, die dir weiter helfen koennten:

        http://discuss.joelonsoftware.com/default.asp?joel.3... Zweitens sind mir ein paar "magische" Konstanten aufgefallen:

        int i,j,k, b[5000];
        

        i, j, k sind ja nur Zeiger, um das Array abzutasten.
        b stellt ein Hilfsarray dar, mH dessen die zu sortierenden
        Mergeteile in die richtige Reihenfolge gebracht werden. Da b
        in meiner Programmierung nur halb so groß ist, wie das
        ursprungsarray, könnte ich es auf 2500 Felder reduzieren.
        Aber noch mehr?
        In meinem dritten Fall, also einer Sortierung von 5000 Zahlen,
        brauche ich doch ebenso viel Platz (bzw 2500 Felder) in dem
        Hilfsarray, oder?
        Du hast ja selbst erklaert, dass die noetige Gruesse von b von der Anzahl der zu sortierenden Elemente abhaengt. Das tut es aber in deinem Programm nicht, darauf wollte ich hinaus. Wenn jemand probiert, die Routine mit 10000 Elementen aufzurufen, wird sie crashen.

        Also muss die Routine die maximale Anzahl an Elementen erfahren, und dementsprechend zur Laufzeit Speicher allokieren.

        Gruesse,
        Moritz

Keine passende Antwort gefunden? Jetzt eigene Frage stellen!