[WinAPI] Größe des Stapelspeichers bestimmen

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

Der Speicher, zu dem man einen Zeiger bekommt, wird im Stack-Frame der aktuellen Funktion reserviert. Und der ist natürlich futtsch, sobald sie zum Aufrufer zurückkehrt – exakt wie alle anderen lokalen Variablen, die dort liegen, eben auch. Ergo ist jeder (m)alloca()-allokierte Zeiger, den man aus einer Funktion kriegt, per Definition ungültig. Ist genau so unsinnig wie char * getMem() { char arr[1000]; return arr; } zu schreiben …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von dot »

:mrgreen: oook, ka was da grad los war, können wir einfach so tun, als hätt ich nie was gesagt? Ich glaub mein Hirn hat da grad irgendwie ausschließlich auf Delta-Ebene gearbeitet oder so...

An meinem Argument mit der Maximalgröße ändert sich dadurch aber nix ;)
Zuletzt geändert von dot am 09.09.2011, 19:03, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

Ja; und ja, ich wollte auch auf keinen Fall an zwei Fronten gleichzeitig kämpfen ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von dot »

Gut, mein Argument von wegen _alloca() fixen war natürlich ziemlich schwachsinnig.Ich würds aber nach wie vor sowieso besser finden, wenn man es gar nicht erst zu einem Stackoverflow kommen lässt. Ich denk, das Verhalten von _malloca() ist eigentlich eine sehr gute Lösung.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von BeRsErKeR »

Krishty hat geschrieben:
dot hat geschrieben:Kann man eine Structured Exception nicht normalerweise einfach mit nem __except fangen?
BeRsErKeR hat geschrieben:Weiterhin ist auf der Seite unten noch ein Beispiel, wie man Stack Overflows ggf. auch abfangen kann. ;)
Ja, da gibt es nur ein enormes Problem: Ich darf _resetstkoflw() nicht während des Stack Unwindings aufrufen. Das bedeutet:
  • nicht von einem catch-Block aus, und
  • nicht von einer SEH-Translator-Funktion aus.
Bleiben nicht viele sinnvolle Möglichkeiten, _resetstkoflw() aufzurufen, oder?
  • in einem __except-Block (der schließt aber jede andere Form von Ausnahmebehandlung aus; d.h. sobald ich einen in meine Funktion schreibe, kann ich dort keine C++-Ausnahmen mehr werfen und es werden keine Destruktoren mehr aufgerufen);
  • nach dem catch-Block, der eine übersetzte Stapelüberlaufausnahme abgefangen hat – das bedeutet aber einerseits, dass ich die umliegenden Textteile mit Fehlerbehandlung schwemme, mit der sie garnichts zu tun haben dürften, und andererseits, dass ich das hinter jedem catch-Block in meinem gesamten Programm machen wüsste, weil ich ja nie weiß, ob das in dem try nicht irgendwann eine Funktion aufruft, die _alloca() oder _malloca aufruft.
Hast du dir mal die Beispiele zum Thema Structured Exception in C++ Exception umwandeln angeguckt? Hier mal der Beispielcode vom einen Link:

Code: Alles auswählen

// crt_resetstkoflw2.cpp
// compile with: /EHa
// _set_se_translator requires the use of /EHa
#include <malloc.h>
#include <stdio.h>
#include <windows.h>
#include <eh.h>

class Exception { };

class StackOverflowException : Exception { };

// Because the overflow is deliberate, disable the warning that
// this function will cause a stack overflow.
#pragma warning (disable: 4717)
void CauseStackOverflow (int i)
{
        // Overflow the stack by allocating a large stack-based array
        // in a recursive function.
        int a[10000];
        printf("%d ", i);
        CauseStackOverflow (i + 1);
}

void __cdecl SEHTranslator (unsigned int code, _EXCEPTION_POINTERS*)
{
   // For stack overflow exceptions, throw our own C++ 
   // exception object.
   // For all other exceptions, throw a generic exception object.
   // Use minimal stack space in this function.
   // Do not call _resetstkoflw in this function.

   if (code == EXCEPTION_STACK_OVERFLOW)
      throw StackOverflowException ( );
   else
      throw Exception( );
}

int main ( )
{
        bool stack_reset = false;
        bool result = false;

        // Set up a function to handle all structured exceptions,
        // including stack overflow exceptions.
        _set_se_translator (SEHTranslator);

        try
        {
            CauseStackOverflow (0);
        }
        catch (StackOverflowException except)
        {
                // Use minimal stack space here.
                // Do not call _resetstkoflw here.
                printf("\nStack overflow!\n");
                stack_reset = true;
        }
        catch (Exception except)
        {
                // Do not call _resetstkoflw here.
                printf("\nUnknown Exception!\n");
        }
        if (stack_reset)
        {
          result = _resetstkoflw();
          // If stack reset failed, terminate the application.
          if (result == 0)
             exit(1);
        }

        void* pv = _alloca(100000);
        printf("Recovered from stack overflow and allocated 100,000 bytes"
               " using _alloca.");

   return 0;
}
Ohne Input kein Output.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von CodingCat »

Krishty hat geschrieben:Bleiben nicht viele sinnvolle Möglichkeiten, _resetstkoflw() aufzurufen, oder?
  • in einem __except-Block (der schließt aber jede andere Form von Ausnahmebehandlung aus; d.h. sobald ich einen in meine Funktion schreibe, kann ich dort keine C++-Ausnahmen mehr werfen und es werden keine Destruktoren mehr aufgerufen);
  • nach dem catch-Block, der eine übersetzte Stapelüberlaufausnahme abgefangen hat – das bedeutet aber einerseits, dass ich die umliegenden Textteile mit Fehlerbehandlung schwemme, mit der sie garnichts zu tun haben dürften, und andererseits, dass ich das hinter jedem catch-Block in meinem gesamten Programm machen wüsste, weil ich ja nie weiß, ob das in dem try nicht irgendwann eine Funktion aufruft, die _alloca() oder _malloca aufruft.
BeRsErKeR hat geschrieben:Hast du dir mal die Beispiele zum Thema Structured Exception in C++ Exception umwandeln angeguckt? Hier mal der Beispielcode vom einen Link:
Was macht dein Beispiel? Es packt nach den catch-Block eine if-Abfrage, um _resetstkoflw aufzurufen ... ;-)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von BeRsErKeR »

Das ist zwar nicht _mein_ Beispiel aber ich habs auch gerade gemerkt. Allerdings könnte man die try-catch-Behandlung doch direkt in der Funktion machen, die alloca aufruft und halt nach dem catch-Block aufräumen und die Exception danach durch ein erneutes throw (ausgelöst durch ein Flag) an den Aufrufer weiterleiten. Oder hat ein try-Block auch einen eigenen Stack? Müsste man zwar für jede Funktion machen, die alloca aufruft, aber ganz ohne Aufwand geht es halt nicht.
Ohne Input kein Output.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von CodingCat »

Ja genau, das ist das Problem, alloca lässt sich nicht in eine eigene Funktion verpacken, und jede Funktion, die Speicher mittels alloca alloziiert, müsste diese umständliche Ausnahmebehandlungslogik redundant implementieren.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von BeRsErKeR »

Nun ja, redundaten Code kann man durch den Präprozessor einfügen lassen (-> Makro). Ist zwar unschön, aber in meinen Augen vertretbar. Man kann hier halt nicht mit Funktionsaufrufen arbeiten und andere Mittel würden mir da nicht einfallen.

Wie sieht es eigentlich mit Inline-Funktionen aus? Die dürften doch theoretisch keinen eigenen Stack besitzen, da sie ja direkt an die Stelle "kopiert" werden, an der sie aufgerufen werden. Könnte man damit vielleicht den Fehlerbehandlungs-Code auslagern, oder macht einem da der Compiler einen Strich durch die Rechnung?
Ohne Input kein Output.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von CodingCat »

BeRsErKeR hat geschrieben:Wie sieht es eigentlich mit Inline-Funktionen aus? Die dürften doch theoretisch keinen eigenen Stack besitzen, da sie ja direkt an die Stelle "kopiert" werden, an der sie aufgerufen werden.
Die Idee ist prinzipiell nicht falsch, aber Inlining ist tatsächlich reine Compilersache, d.h. es gibt keinerlei Garantie dafür, dass geinlinet wird, und auch keinerlei Garantie über den Aufbau des Stacks, wenn geinlinet wird. Rein semantisch verhalten sich Inline-Funkionen wie alle anderen Funktionen auch, und das heißt, nach Ablauf wird alles darin zerstört, ob der Text nun kopiert oder aufgerufen wurde.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

Man darf _resetstkoflw() tatsächlich nicht von einem catch-Block aus aufrufen:
It is not safe to call _resetstkoflw in a C++ catch block that is reached from an exception thrown by the structured exception translator function. In this case, the stack space is not freed and the stack pointer is not reset until outside the catch block, even though destructors have been called for any destructible objects before the catch block.
Ähnliches gilt auch für __except-Blöcke – darum die Pfriemelei mit den ifs.

Inline-Funktionen sind ebenfalls keine Möglichkeit: Funktionen, die try, catch, __try, __except oder __finally enthalten, werden sowieso nie geinlined. Der Grund ist die Architektur der Ausnahmebehandlung, die für die Installation solcher Blöcke spezielle Daten im Funktionskopf (x86) bzw. einer Funktionstabelle (x64) platzieren muss und das nicht doppelt tun kann.

Darum sind wir hier alle so überzeugt, dass das Beste wäre, die Allokation überhaupt garnicht erst fehlschlagen zu lassen. Ich verstehe auch, was dot mit der Berechenbarkeit von einer festen Grenze meint: Ich kann statisch anhand meines Aufrufbaums voraussagen, wann maximal wie viel meines Stapels belegt ist. Würde ich die Allokationsgrenze stattdessen nach der noch freien Größe richten, hätte ich an kaum einer Stelle statische Garantie dafür, wie viel Stapelspeicher noch frei ist. Und das stimmt absolut.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von dot »

Krishty hat geschrieben:Ich verstehe auch, was dot mit der Berechenbarkeit von einer festen Grenze meint: Ich kann statisch anhand meines Aufrufbaums voraussagen, wann maximal wie viel meines Stapels belegt ist. Würde ich die Allokationsgrenze stattdessen nach der noch freien Größe richten, hätte ich an kaum einer Stelle statische Garantie dafür, wie viel Stapelspeicher noch frei ist. Und das stimmt absolut.
Jap, genau das mein ich damit :)
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von BeRsErKeR »

Mir drängt sich irgendwie die Frage auf warum du für deine Strings keine std::strings nutzt. Das Weglassen der terminierenden Null in deinen Strings wird ja wohl kaum daher rühren, dass du dadurch Speicherplatz sparen willst, sondern eher weil du die Variante mit Längenangabe schöner, sinnvoller oder so ähnlich findest. Und deine eigene Stringklasse könnte ja einfach einen std::string als internen Buffer nutzen auf dem sie ggf. zusätzliche Operationen ausführen kann.

Ein std::string kann ja alles von Haus aus. Du musst keine terminierende Null nutzen.

Beim Erstellen: std::string ( const char * s, size_t n );
Beim Zuweisen: std::string& assign ( const char* s, size_t n );
Beim Auslesen/Kopieren: std::string::data ( );

Und direkt aus Streams lesen geht ja bekanntlich über std::istream& std::getline ( std::istream& is, std::string& str, char delim ); etc.

Für die WINAPI kannst du dann bequem std::string::c_str ( ); nutzen, welches dir automatisch die terminierende Null dranhängt. Ich gehe mal stark davon aus, dass die Klasse so clever ist und für die '\0' bereits vorher Speicher mit reserviert. Du hast zwar ggf. einen kleinen Overhead an Speicherverbrauch, aber der sollte vernachlässigbar gering sein. Du hast aber nicht den Aufwand da selbst was zu erfinden. Von daher weiß ich nicht so recht welchen Grund du hast, keine std::strings zu nutzen.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

Die STL benutze ich schon seit fast zwei Jahren nicht mehr, weil sie überladen, im Funktionsumfang den Compiler-Möglichkeiten hinterherhinkend und zumindest unter VC mies implementiert und nicht ansatzweise so leistungsfähig ist, wie sie sein sollte. <new> ist der einzige Standard-Header, der mir noch in den Text kommt; und das auch nur, weil er zu fest mit der Sprache verdrahtet ist, um ihn rauszunehmen :(

Das Anfügen der Null ist nur ein Problem von vielen. Ich bin der Meinung, dass alles, das eine Lebenszeit von einem einzigen Funktionsaufruf hat, auf dem Stapel landen sollte. Leider bin ich damit wohl allein.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von BeRsErKeR »

Krishty hat geschrieben:Das Anfügen der Null ist nur ein Problem von vielen. Ich bin der Meinung, dass alles, das eine Lebenszeit von einem einzigen Funktionsaufruf hat, auf dem Stapel landen sollte. Leider bin ich damit wohl allein.
Ich denke eigentlich dass viele (mich einbegriffen) diese Einstellung teilen. Wenn ich z.B. sehe, dass manche Leute sowas schreiben:

Code: Alles auswählen

void func()
{
    MyClass *foo = new MyClass;

    ...

    delete foo;
}
kräuseln sich bei mir die Zehnägel. Es ist nicht nur sinnlos, sondern in dem Fall auch gefährlich.

Das Problem am Stack ist halt, dass er relativ klein ist und es leider keine guten Möglichkeiten gibt Zugriffsfehler bzw. Stackoverflows abzufangen. Allerdings hatte ich bislang auch noch nie Probleme damit, dass mir eventuell der Stackspeicher zur Neige geht.

In deinem Fall frage ich mich auch wann du mal so große Strings hast, dass sie den Stack sprengen. In der Regel ist ein Stack 1 MB groß und so lange Strings hat man in der Regel nie, es sei denn du verarbeitest komplette Dateiinhalte. Aber dafür gibts ja wie schon geklärt _malloca oder du bietest für Fälle, in denen man von großen Längen ausgehen kann, eine zweite Funktion an, die auf dem Heap arbeitet.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

BeRsErKeR hat geschrieben:Das Problem am Stack ist halt, dass er relativ klein ist
Der Stapel ist so groß, wie du ihn in deinem Linker einstellst. Niemand hält dich davon ab, 2 GiB zu reservieren – das Problem ist nur, dass sich das System vom Stapel (im Gegensatz zum Freispeicher) keinen ungenutzten Speicher mehr zurückholen kann; d.h., wenn du einmal eine Funktion lang die volle Größe allokiert hattest, wirst du den Brocken im Task-Manager nicht mehr los. (Ist imo aber nur halb so schlimm, da die meisten Programme entweder einmal zur Spitzenleistung anlaufen und dann direkt wieder runterfahren oder ihre Spitzenleistung Frame für Frame aufrechterhalten.)
BeRsErKeR hat geschrieben:und es leider keine guten Möglichkeiten gibt Zugriffsfehler bzw. Stackoverflows abzufangen.
Inwiefern man Zugriffsfehler abfangen sollte, weiß ich nicht. Bei Stapelüberläufen bin ich mir durch diesen Thread auch nicht mehr so sicher :/

Zu dem Beispiel: Ja, das ist sowieso unterste Schublade. Leider ist

void func() {
    ::std::string str = "blubb";
}


zwar nicht so ein Beispiel für RAII-Unwissen, verschwendet aber genauso, da es ja auf dem Freispeicher allokiert, um beim Verlassen der Funktion sofort wieder zu zerstören.

Vllt könnte man für solche Fälle einen Allokator bauen, dem man einen via alloca() allokierten Bereich übergibt, und der ihn dann dem String zur Verfügung stellt …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von dot »

Imo müsste man für einen solchen String, der am Stack allokiert, einen eigenen Typ haben, für den der operator new nur deklariert, nicht aber definiert ist, oder der keinen öffentlichen Konstruktor hat, oder für den sonst irgendwelche Maßnahmen ergriffen wurden, um zu verhindern, dass ein solches Objekt einen anderen als lokalen Scope bekommt. Denn wenn ich so ein String-Objekt z.B. mit new erzeugen würde, dann hätte es potentiell anderen Scope, als der Buffer, den es verwendet.
Ein Allocator allein würds also nicht tun, du müsstest imo eine Spezialisierung von std::basic_string für deinen Allocator anlegen.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4856
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Schrompf »

Krishty, in Deinem Beispiel wird übrigens kein Speicher vom Heap allokiert. std::string hat (genauso wie der zugrundeliegende std::vector) eine Optimierung für kleine Ausmaße, bei der der Buffer direkt im Objekt gehalten wird. Bewirkt für kleine Strings unglaubliche Verbesserungen, geht aber nur bis 16 Byte inklusive terminierendem 0-Byte.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

@dot: Stimmt. Damn, stack — you scary …

@Schrompf: Ups ja, völlig korrekt. Ich meinte natürlich ::std::string str = "blubbedi blubb-blub";
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von BeRsErKeR »

Was ich mich noch frage ist, wie dynamisch wachsende Arrays auf dem Stack überhaupt möglich sein sollen, ohne auf Dauer den Stack vollzuhauen. Ich meine sagen wir mal man alloziert sich 100 Byte mit _alloca. Dann benötigt man später zusätzliche 50 Byte. Man kann ja dann nicht davon ausgehen, dass die neuallozierten 50 Byte genau hinter den 100 Byte liegen, sprich man muss um zusammenhängende Daten (z.B. einen null-terminierten C-like String) zu erhalten die vollen 150 Byte neu allozieren, wodurch die 100 Byte von vorher verschenkt sind. Wenn man das häufiger in einer Funktion macht verschwendet man doch ständig Speicher. Und wie wär es z.B. wenn ich ein Zeichen aus dem String löschen will? Z.B. aus der Mitte? Da komm ich doch auch nicht um komplette Neuallokation rum, oder seh ich da was falsch?
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

Nö; Reallokationen gehen auch nicht … ich weiß aber auch nicht, warum das ein Problem sein sollte – eigentlich sind meine Daten so angelegt, dass ich in 99 % der Fälle weiß, wie viel kommen wird. Außerdem ist „auf Dauer“ schon kühn gewählt … die Daten sind ja wieder weg, sobald die Funktion verlassen wird. D.h., all diese Reallokationen müssten sich innerhalb eines Aufrufstapels ereignen … riecht nach was, was nicht sein sollte.

Was das Löschbeispiel angeht: Wenn ich einen String eh lokal kopiere, kann ich diesen Buchstaben auch direkt beim Kopieren weglassen. Zack – Reallokation weg, das eine Byte verschwendeten Stapels weg und weniger Kopiererei.
Zuletzt geändert von Krishty am 15.09.2011, 22:26, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von dot »

Nein das siehst du richtig. Für sowas wären solche strings aber wohl auch nicht gedacht ;)
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von BeRsErKeR »

Krishty hat geschrieben:Was das Löschbeispiel angeht: Wenn ich einen String eh lokal kopiere, kann ich diesen Buchstaben auch direkt beim Kopieren weglassen. Zack – Reallokation weg, das eine Byte verschwendeten Stapels weg und weniger Kopiererei.
Nun ja gehen wir mal von folgendem Szenario aus. Ich übergebe einer Funktion einen Dateinamen als String. In der Funktion sollen 3 Dateien mit gleichem Namen aber anderer Dateiendung angelegt werden. Wenn ich hier wirklich nach dem Grundsatz arbeite, dass ich alles was ich nur in der Funktion benötige, auch nur auf deren Stack anlege, dann brauch ich hier schon mindestens 4 Allokationen. Sicher könnte man dieses Beispiel auch über 3 verschiedene Funktionen lösen, die dann jeweils nur einen der Dateinnamen in ihrem Stack anlegen und verarbeiten.

Oder wie sieht es denn aus, wenn ich einen String in einer Funktion anlege und alle Kommata löschen will? Dazu würde mir mit einer einzigen Allokation nur einfallen, dass man zunächst die Anzahl der Kommata zählt und den neuen String dann in dieser Größe anlegt und beim Kopieren halt nur die Teile ohne Komma kopiert. Das Zählen könnte ich mir sonst jedoch sparen.

Prinzipiell lassen sich wohl die meisten "Probleme" wirklich umgehen. Das ist wohl auch eher ein Problem an sich und keins des Stacks, nur dass man im Heap halt den gleichen Bereich öfter nutzen kann, wenn man ihn vorher freigibt.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

BeRsErKeR hat geschrieben:Nun ja gehen wir mal von folgendem Szenario aus. Ich übergebe einer Funktion einen Dateinamen als String. In der Funktion sollen 3 Dateien mit gleichem Namen aber anderer Dateiendung angelegt werden. Wenn ich hier wirklich nach dem Grundsatz arbeite, dass ich alles was ich nur in der Funktion benötige, auch nur auf deren Stack anlege, dann brauch ich hier schon mindestens 4 Allokationen.
Warum vier? Drei für die drei neuen Dateinamen plus Endung; wobei man die natürlich auch in einem Rutsch allokieren kann. Aber selbst, falls es vier sind: Na und? Die tun doch keinem was.
BeRsErKeR hat geschrieben:Oder wie sieht es denn aus, wenn ich einen String in einer Funktion anlege und alle Kommata löschen will? Dazu würde mir mit einer einzigen Allokation nur einfallen, dass man zunächst die Anzahl der Kommata zählt und den neuen String dann in dieser Größe anlegt und beim Kopieren halt nur die Teile ohne Komma kopiert. Das Zählen könnte ich mir sonst jedoch sparen.
Naja; du kannst natürlich auch schon bei der Erzeugung zählen oder direkt weglassen. Aber hier auch wieder: Na und? Zählen, auf dem Stapel allokieren und kopieren ist schneller als es zählen, auf dem Freispeicher allokieren und kopieren wäre.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Helmut »

Mich würd mal interessieren ob du das Problem jetzt eigentlich gelöst hast. Und vor allem wie :)
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

Garnicht; zu viel anderes in die Quere gekommen :) Aber wenn, hätte ich ein bad_alloc() bei zu großen Anfragen geschmissen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8245
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Größe des Stapelspeichers bestimmen

Beitrag von Krishty »

Nur als kleiner Nachtrag damit ich das nicht vergesse, wenn ich in hundert Jahren auf das Thema zurückkomme:

void __stdcall RtlpGetStackLimits(ULONG_PTR * Lower, ULONG_PTR * Higher);
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten