Unangenehmes Problem mit sprintf_s
-
Hehe ja OK. Ich bin ja schon sehr froh, dass dies ein bekanntes Phänomen von sprintf_s ist, ich befürchtete bereits, dass der eigentliche Fehler vielleicht noch viel tiefer sitzt, weil ich das Ganze mit einer simplen Konsolenapplikation nicht nachbilden konnte:
int main(){ char szBuf[16]; sprintf_s(szBuf,4096,"Hallo"); return 0; }
Dieses Programm stürzt nämmlich aus irgendeinem Grund nicht ab?? Der müsste doch eigentlich die Grenzen des aktuellen Threadstacks überschreiben und in jedem Fall eine Speicherschutzverletzung auslösen? Wieso passiert dann bei diesem Code nichts?
-
Ich finde es immer wieder witzig, wie Leute probieren mit undefiniertem Verhalten zu argumentieren. Undefiniertes Verhalten heisst nicht Absturz, es heisst undefiniert
Ishildur schrieb:
Mit ANSI C++ IMHO nichts, aber ich dachte mir, im C Forum hätten Sie vermutlich den Code nicht verstanden...
Und wieso sollten wir es im C++ Forum eher verstehen?
Darf ich auch noch fragen, wieso du
sprintf_s
verwenden willst? Gerade wenn es dir um Sicherheit geht, gäbe es in C++ doch bessere und sichere Möglichkeiten.Grüssli
-
Dravere schrieb:
Darf ich auch noch fragen, wieso du
sprintf_s
verwenden willst? Gerade wenn es dir um Sicherheit geht, gäbe es in C++ doch bessere und sichere Möglichkeiten.Die Umstellung von sprintf auf sprintf_s ist einfach weitaus billiger und zeitsparender als auf streams oder boost.
-
Shade Of Mine schrieb:
Dravere schrieb:
Darf ich auch noch fragen, wieso du
sprintf_s
verwenden willst? Gerade wenn es dir um Sicherheit geht, gäbe es in C++ doch bessere und sichere Möglichkeiten.Die Umstellung von sprintf auf sprintf_s ist einfach weitaus billiger und zeitsparender als auf streams oder boost.
Also im Sinne von:
A> "Wir wollen mehr Sicherheit im Programm!"
B> "Wir benutzen C++, lass uns die Sicherheit von C++ nutzen!"
A> "So sicher soll es auch wieder nicht sein, dass wäre viel zu teuer umzustellen."
B> "..."Aber ok, wie wäre es dann zumindest damit, dass die Puffer auf
std::vector
oderstd::tr1::array
Objekte umgestellt werden? So wird gleich auch die Grösse mitübergeben, welche man dann insprintf_s
verwenden kann.Grüssli
-
Ishildur schrieb:
Dieses Programm stürzt nämmlich aus irgendeinem Grund nicht ab?? Der müsste doch eigentlich die Grenzen des aktuellen Threadstacks überschreiben und in jedem Fall eine Speicherschutzverletzung auslösen? Wieso passiert dann bei diesem Code nichts?
Für den Stack wird nicht explizit Speicher angefordert. Es wird einfach drauf los geschrieben. Das Betriebssystem weiß daher gar nicht, dass du in deinem C Programm nur Platz für 16 chars vorsiehst. Der Speicherbereich für den Stack hat einfach zu Beginn eine gewisse Größe (afaik ist 1 MB bei Windows Standard) und kann theoretisch bei Bedarf automatisch weiter wachsen. Daher kommt es dort nicht zu Speicherschutzverletzungen wenn man zu viel drauf schreibt.
Der Grund warum es bei Pufferüberläufen auf dem Stack oft knallt, ist dass dort die Rücksprungadressen stehen. Beim Aufruf einer Funktion wird die aktuelle Adresse dort gespeichert und beim return wird dort wieder hin gesprungen. Wenn die Adresse nun mit irgendeinem falschen Wert überschrieben wurde, springt man ins Nirwana.
-
@Dravere
Ich habe 90% der Applikation mit reinem C implementiert (die C++ Standardbibliothek habe ich nicht angerührt. Ah doch, std::type_info benutze ich. Ich verwende C++ in diesem Projekt ausschliesslich wegen der Templates sowie der Laufzeitpolymorphie. Der Grund liegt darin begründet, dass wir ein Computerspiel als Abschlussarbeit programmieren und Geschwindigkeit an erster Stelle steht. Glaub mir, ich hatte zu beginn die C++ Standard Bibliothek sowie auch die STl umfangreich benutzt, habe jedoch in Folge von Profiling immer mehr C++ Komponenten durch C oder durch eigene Konstrukte ersetzt, weil diese einfach einen nicht hinzunehmenden Overhead hatten. Die std::map benötigte bspw. einfach mal ca. 800 mal länger, um sämtliche Elemente innerhalb der Map zu löschen als bspw. der von mir entwickelte RedBlackTree (Wir haben einige temporäre Bäume, die einmal pro Frame aufgebaut und schliesslich wieder gelöscht werden müssen) Oder die Umstellung einer std::list auf ein natives C Array innerhalb eines kritischen Algorithmus innerhalb der Textengine hatte die Framerate einfach so mal verdoppelt von 500 auf 1000 fps. Die gesamte InGame Konsole benötigt durch die Umstellung von std::string auf cirkuläre c-strings noch ein einziges New und ein einziges Delete während der gesamten Lebensdauer der Applikation und nicht mehr zwischen 10 - 20 news und deletes pro Frame.Natürlich hat das alles einen hohen Preis: Ich muss bspw. dem RedBlackTree sagen, wie gross er maximal werden darf und wie hoch die maximale Suchtiefe sein kann und wehe das wird überschritten, genauso wie bspw. die Konsole. Im Konstruktor übergebe ich die Anzahl Zeilen sowie die Anzahl Spalten und dann alloziiere ich einen entsprechend grossen Speicherbereich (EINMAL) und dann verwalte ich diesen Speicherbereich innerhalb des Programms und kopiere nicht bei jeder neuen Eingabe zig strings hin und her und alloziiere hier wieder Speicher und muss da wieder was freigeben...
Ich weiss doch auch nicht, vielleicht haben wir alles falsch gemacht aber wir haben uns für einen Weg entschieden und den werden wir jetzt auch so zu Ende gehen (in ca. 1.5 Monaten ist Abgabetermin) und da werde ich jtzt sicher nicht wieder alles auf die C++ Bibliothek umstellen (Was wir zu beginn hatten und nicht schnell genug war)...
Eines aber noch Dravere, wie machst du mit C++ iostreams folgendes:
"Mein Name ist %s und wohne in %s seit %s"
"My name is %s and I live in %s since %s"
....
....Diese Strings werden extern gespeichert und werden schliesslich eingelesen und von sprintf_s verarbeitet. Die Positionen der Variablen innerhalb eines Strings kann von Sprache zu Sprache unterschiedlich ausfallen!
-
Ishildur schrieb:
Die std::map benötigte bspw. einfach mal ca. 800 mal länger, um sämtliche Elemente innerhalb der Map zu löschen als bspw. der von mir entwickelte RedBlackTree (Wir haben einige temporäre Bäume, die einmal pro Frame aufgebaut und schliesslich wieder gelöscht werden müssen)
Klasse bauen, fertig. Kann man auch den C code nehmen und kapseln.
Oder die Umstellung einer std::list auf ein natives C Array innerhalb eines kritischen Algorithmus innerhalb der Textengine hatte die Framerate einfach so mal verdoppelt von 500 auf 1000 fps.
Diese framezahlen habe ich jetzt einfach mal ueberlesen. aber list und array sind unterschiedliche datenstrukturen.
Die gesamte InGame Konsole benötigt durch die Umstellung von std::string auf cirkuläre c-strings noch ein einziges New und ein einziges Delete während der gesamten Lebensdauer der Applikation und nicht mehr zwischen 10 - 20 news und deletes pro Frame.
nocopy strings nehmen oder strings aus einem statischen memory pool aufbauen...
Ich weiss doch auch nicht, vielleicht haben wir alles falsch gemacht aber wir haben uns für einen Weg entschieden und den werden wir jetzt auch so zu Ende gehen (in ca. 1.5 Monaten ist Abgabetermin) und da werde ich jtzt sicher nicht wieder alles auf die C++ Bibliothek umstellen (Was wir zu beginn hatten und nicht schnell genug war)...
Der Fehler war von C++ wegzugehen
Denn du hast kein Argument gegen C++ genannt nur gegen bestimmte klassen die sich aber problemlos ersetzen lassen.
Eines aber noch Dravere, wie machst du mit C++ iostreams folgendes:
"Mein Name ist %s und wohne in %s seit %s"
"My name is %s and I live in %s since %s"
....
....Diese Strings werden extern gespeichert und werden schliesslich eingelesen und von sprintf_s verarbeitet. Die Positionen der Variablen innerhalb eines Strings kann von Sprache zu Sprache unterschiedlich ausfallen!
boost::format
aber wenn man C programmiert oder C code warten muss, ist sprintf_s natuerlich eine gute wahl. nur bei einer neuentwicklung... ich weiss nicht.
-
@Shade Of Mine
Klasse bauen, fertig.
Habe ich ja genauso gemacht?
Diese framezahlen habe ich jetzt einfach mal ueberlesen.
Glaubst du mir etwa nicht?
aber list und array sind unterschiedliche datenstrukturen.
Ja ich habe mich verschrieben, war natürlich ein std::vector
Der Punkt dabei war einfach, dass ich für die Textengine (1000fps, was du mir ja nicht glaubst) ein deferred Rendering verwende. Sprich, wenn ich SpriteBatch::DrawText aufrufe, wird noch gar nichts gezeichnet, sondern der entsprechende Text als DrawJob gespeichert. Schliesslich wird einmal pro Frame der komplette Text mit Hilfe eines einzigen Rendercalls gerendert. Dafür muss aber nach jedem Frame der std::vector der Drawjobs komplett entleert werden. Mit einem nativen c - array war dieser Enleerungsprozess jedoch hinfällig, weil ich stattdessen die DrawJobs da lasse wo sie sind und stattdessen eifach den Zeiger wieder auf das erste Element setze, so werden die alten Drawjobs nach und nach überschrieben. (Was eigentlich jedes Betriebssystem auch so macht, wird ja auch nicht jedes bit mit null überschrieben, wenn eine Datei gelöscht wird...)Sprite aSpr[MAX_SPRITE]; uint32 cSpr = 0; void SpriteBatch::DrawText(){ this->aSpr[this->cSpr++] = // kompliziert... :-p } void Render(){ for(uint32 i=0;i<this->cSpr;++i){ // in VertexBuffer abfüllen } IDirect3DDevice9::DrawIndexedPrimitive(); // die Sprites werden nicht gelöscht oder alle auf null gesetzt oder // sonst irgendwas this->cSpr = 0; }
Der Fehler war von C++ wegzugehen
Ja ich habs vielleicht falsch ausgedrückt, als ich sagte, ich hätte zu 90% in C programmiert meinte ich, dass ich fast ausschliesslich die C Standard Bibliothek anstelle der C++ Standard Bibliothek verwende oder dann grad komplett eigene Implementierungen geschrieben habe.
oder strings aus einem statischen memory pool aufbauen
Genau das mache ich doch??
Denn du hast kein Argument gegen C++ genannt nur gegen bestimmte klassen die sich aber problemlos ersetzen lassen.
Genau das mache ich doch?? Ich finde C++ super, nur viele der Standardbibliotheken passen mir nicht und habe ich desshalb durch eigene Implementationen ersetzt.
-
@Shade Of Mine
Das mit den Framezahlen habe ich mit Fraps nachgemessen um sicherzustellen, dass ich keinen Fehler in der Berechungsformel habe.
-
Ich vermute bei den Problemen mit std::vector etc. eher, dass Debugmodus und/oder checked Iterators (die z.B. bei MSVC++ auch im Releasemodus explizit deaktiviert werden müssen) vermessen wurden. Gerade das "entleeren" eines std::vector sollte nichts kosten, da std::vector beim Verkleinern nicht reallokiert. Und wenn die im std::vector gespeicherten Strukturen PODs sind, findet auch kein Destruktoraufruf statt (und wenn es keine PODs sind, müssen auch die Elemente im C-Array destruiert werden).
-
Ishildur schrieb:
Diese framezahlen habe ich jetzt einfach mal ueberlesen.
Glaubst du mir etwa nicht?
Die Zahlen sind komisch. FPS ist kein sehr guter Indikator für die tatsächliche Geschwindigkeit.
Fraglich ist, wie gemessen wurde und wie relevant das Ergebnis ist. Wenn mit einer Auflösung von 1 ms gemessen wurde, kann schon ein tatsächlicher Unterschied von lediglich 0.01 ms zu so einem drastischen Sprung des angezeigten Messwerts führen. Da du ausgerechnet 1000 und 500 genannt hast, liegt es nahe, dass das hier passiert sein könnte.
Außerdem stellt sich die Frage, wie relevant diese Messung ist, weil für ein Spiel weder 500 Hz noch 1000 Hz vernünftig sind. Ein Spiel läuft heutzutage in der Regel mit 60 FPS; auf diese realistische Frequenz umgerechnet beträgt der Unterschied nur noch ein paar Prozent. Und das auch nur, wenn tatsächlich exakt gemessen wurde, und nicht im 1 ms-Raster.
Diese paar Prozent, die nachher vielleicht gar nicht relevant sind, hast du dir durch mehr Entwicklungsaufwand erkauft. Und vielleicht mehr Debugging-Aufwand, wenn sich Fehler eingeschlichen haben die mit erprobten Strukturen nicht aufgetreten wären.LordJaxom schrieb:
Ich vermute bei den Problemen mit std::vector etc. eher, dass Debugmodus und/oder checked Iterators (die z.B. bei MSVC++ auch im Releasemodus explizit deaktiviert werden müssen) vermessen wurden.
Ein sehr gern gemachter Fehler beim Messen.
-
die z.B. bei MSVC++ auch im Releasemodus explizit deaktiviert werden müssen
Hoppla, ja da hatte ich tatsächlich nichts entsprechendes deaktiviert, wie mache ich denn das?
Fraglich ist, wie gemessen wurde und wie relevant das Ergebnis ist. Wenn mit einer Auflösung von 1 ms gemessen wurde, kann schon ein tatsächlicher Unterschied von lediglich 0.01 ms zu so einem drastischen Sprung des angezeigten Messwerts führen. Da du ausgerechnet 1000 und 500 genannt hast, liegt es nahe, dass das hier passiert sein könnte.
Ich benutze den QueryPerformanceCounter also nix 1ms Raster :p
Außerdem stellt sich die Frage, wie relevant diese Messung ist, weil für ein Spiel weder 500 Hz noch 1000 Hz vernünftig sind. Ein Spiel läuft heutzutage in der Regel mit 60 FPS
Da bin ich anderer Meinung. Auf die 60Hz kommt man IMHO durch das V-Sync (Das man IMHO ruhig ausschalten kann, da Flachbildschirme ohnehin keinen Ionenestrahl mehr haben der Zeile für Zeile die Phosphorteilchen zum leuchten bringt) 60Hz ist für das Auge durchaus vernünftig und völlig ausreichend, nicht jedoch für die Haptik, da wärend 1kHz und mehr durchaus wünschenswert...
-
Ishildur schrieb:
die z.B. bei MSVC++ auch im Releasemodus explizit deaktiviert werden müssen
Hoppla, ja da hatte ich tatsächlich nichts entsprechendes deaktiviert, wie mache ich denn das?
http://msdn.microsoft.com/en-us/library/aa985965.aspx
Ishildur schrieb:
Da bin ich anderer Meinung. Auf die 60Hz kommt man IMHO durch das V-Sync (Das man IMHO ruhig ausschalten kann, da Flachbildschirme ohnehin keinen Ionenestrahl mehr haben der Zeile für Zeile die Phosphorteilchen zum leuchten bringt)
Das ist völliger Humbug. VSync ist bei LCD immer noch nötig. Wenn die Graphikkarte mit höherer Geschwindigkeit Bilder produziert als der Bildschirm Herz hat, dann kann es immernoch zu Überlappungen kommen, weil womöglich zu dem Zeitpunkt, als sich der Bildschirm sein Bild holte, die Graphikkarte gerade in den Puffer am schreiben war.
Ishildur schrieb:
Der Punkt dabei war einfach, dass ich für die Textengine (1000fps, was du mir ja nicht glaubst) ein deferred Rendering verwende. Sprich, wenn ich SpriteBatch::DrawText aufrufe, wird noch gar nichts gezeichnet, sondern der entsprechende Text als DrawJob gespeichert. Schliesslich wird einmal pro Frame der komplette Text mit Hilfe eines einzigen Rendercalls gerendert. Dafür muss aber nach jedem Frame der std::vector der Drawjobs komplett entleert werden. Mit einem nativen c - array war dieser Enleerungsprozess jedoch hinfällig, weil ich stattdessen die DrawJobs da lasse wo sie sind und stattdessen eifach den Zeiger wieder auf das erste Element setze, so werden die alten Drawjobs nach und nach überschrieben. (Was eigentlich jedes Betriebssystem auch so macht, wird ja auch nicht jedes bit mit null überschrieben, wenn eine Datei gelöscht wird...)
Also das musst du mir jetzt nochmals genauer erklären. Wieso müsste eigentlich ein
std::vector
entleert werden, ein C Array aber nicht? Wer zwingt dich überhauptclear
aufzurufen? Abgesehen davon, dass natürlich einclear
eigentlich gar keinen Speicher freigeben würde. Das klingt für mich, dass dustd::vector
regelmässig gelöscht und neu Speicher reservieren hast lassen und dich dann darüber wunderst, wenn du dies mit einem C Array nicht machst, dass es schneller ist.Da bekommt man doch etwas Zweifel an deinen Performance-Messungen
Ishildur schrieb:
oder strings aus einem statischen memory pool aufbauen
Genau das mache ich doch??
Nein, du verwendest schlicht und einfach C Strings mit einem Memory Pool. Dabei gäbe es Möglichkeiten sowas zu kapseln. Man könnte zum Beispiel einen Memory Pool erstellen und die
std::string
von dort ihren Speicher holen lassen. Oder man erstellt Views auf den Speicher mit eigenen Klassen. Es gäbe verdammt viele Möglichkeiten sowas zu optimieren und zwar auch direkt mit der STL.Es gäbe zum Beispiel auch die Möglichkeiten den Allocator zu ändern oder man kann sich Klassen bauen, welche automatisch Speicher aus einem Memory Pool besorgen, wenn einem die Allocators zu unangenehm sind.
Ein Stichwort wäre hier zum Beispiel: Small Object Allocator.
Eine mögliche Implementation hat Andrei Alexandrescu in seinem Buch Modern C++ Design vorgestellt. Der Code ist im Internet in der Loki Bibliothek vorhanden:
http://loki-lib.sourceforge.net/
http://loki-lib.cvs.sourceforge.net/loki-lib/loki/include/loki/SmallObj.h?view=markupDaran sieht man, was für Möglichkeiten einem offen stehen und man kann das für seine Zwecke verändern.
Genau das mache ich doch?? Ich finde C++ super, nur viele der Standardbibliotheken passen mir nicht und habe ich desshalb durch eigene Implementationen ersetzt.
Das sieht aber nicht wirklich danach aus. Es sieht mehr nach einem C mit Klassen aus. Schon nur deine C Strings deuten darauf hin, welche du nicht sinnvoll gekapselt hast. Wahrscheinlich auch an vielen Orten Dinge wie RAII missachtet, usw. usf.
Es sieht hauptsächlich danach aus, als wenn du die C++ Standardbibliothek weggeworfen hast und nun die C Bibliothek einsetzt und dies einfach in Klassen. Das ist aber kein sinnvoller und sicherer Ersatz.Für eine Korrektur ist es sicherlich zu spät, da stimme ich dir zu. Nur solltest du vielleicht aufpassen, was du in die Arbeit schreibst, wieso du so programmiert hast. Und für die Zukunft gibt es noch einiges zu lernen
Grüssli
-
Ishildur schrieb:
Ich benutze den QueryPerformanceCounter also nix 1ms Raster :p
Ok. Kannst du mal den Code zeigen, der aus der gemessenen Zeit die Frequenz für die Anzeige berechnet?
Ishildur schrieb:
Außerdem stellt sich die Frage, wie relevant diese Messung ist, weil für ein Spiel weder 500 Hz noch 1000 Hz vernünftig sind. Ein Spiel läuft heutzutage in der Regel mit 60 FPS
Da bin ich anderer Meinung. Auf die 60Hz kommt man IMHO durch das V-Sync (Das man IMHO ruhig ausschalten kann, da Flachbildschirme ohnehin keinen Ionenestrahl mehr haben der Zeile für Zeile die Phosphorteilchen zum leuchten bringt) 60Hz ist für das Auge durchaus vernünftig und völlig ausreichend, nicht jedoch für die Haptik, da wärend 1kHz und mehr durchaus wünschenswert...
Zu dem was Dravere dazu geschrieben hat möchte ich noch hinzufügen, dass ich den Sinn von Optimierungen fragwürdig finde, die dazu dienen, die Anzahl der berechneten, aber letztlich sowieso unsichtbaren Bilder von 440 auf 940 zu steigern
Und die Sache mit der Haptik... 1000 Hz liegt mit Sicherheit weit jenseits der Abfragefrequenz von so ziemlich jedem Eingabegerät. Es würde mich wundern, wenn irgendein Gerät öfter als vielleicht 100x pro Sekunde abgefragt würde.
-
Das ist völliger Humbug. VSync ist bei LCD immer noch nötig.
Ja meinetwegen, ich habe zusammen mit meinem Partner 5 Testgeräte, das Spiel hat überall unterschiedliche Frameraten, ein Flackern oder sonstige typische Effekte von ausgeschaltetem V-Sync konnten wir nirgends wahrnehmen, sollte sich dies ändern hat der Spieler jederzeig die Möglichkeit, V-Sync einzuschalten.
Wer zwingt dich überhaupt clear aufzurufen?
Kannst du mir jetzt mal erklären, wieso DU uuuuuuunbedingt einen std::vector benutzen willst (und mich als völligen Idiot hinstellst, weil ich es nicht tue) wenn du die von der std::vector Klasse gegenüber einem nativen array erweiterte Funktionalität überhaupt nicht benutzt?
ein, du verwendest schlicht und einfach C Strings mit einem Memory Pool. Dabei gäbe es Möglichkeiten sowas zu kapseln. Man könnte zum Beispiel einen Memory Pool erstellen und die std::string von dort ihren Speicher holen lassen. Oder man erstellt Views auf den Speicher mit eigenen Klassen. Es gäbe verdammt viele Möglichkeiten sowas zu optimieren und zwar auch direkt mit der STL.
Ja da gebe ich dir völlig recht, das hätte man durchaus tun können. Angesichts der knappen Zeit habe ich aber die in meinen Augen deutlich weniger aufwändige Alternative mit C-Strings für die wenigen Stellen, an der dies notwenig ist bevorzugt, anstatt ein komplettes Framework zu schreiben, welches schliessch an 1, 2 Stellen im Programm benutzt wird.
Und für die Zukunft gibt es noch einiges zu lernen
Wer kann das nicht von sich behaupten? :p
-
Ishildur schrieb:
Wer zwingt dich überhaupt clear aufzurufen?
Kannst du mir jetzt mal erklären, wieso DU uuuuuuunbedingt einen std::vector benutzen willst (und mich als völligen Idiot hinstellst, weil ich es nicht tue) wenn du die von der std::vector Klasse gegenüber einem nativen array erweiterte Funktionalität überhaupt nicht benutzt?
1. Ich will dich nicht als völligen Idioten hinstellen. Ich will dir nur mögliche Fehler aufzeigen, da man aus Fehlern lernt.
2. Du willst mir doch nicht sagen, dassstd::vector::clear
aus deiner Sicht die einzige andere Funktionalität zu einem C Array darstellt?
Zudem gäbe es, wie ich schon früher mal sagte, die Möglichkeit vonstd::tr1::array
, bzw.boost::array
, falls du statische Arraygrössen hast.Ishildur schrieb:
Ja da gebe ich dir völlig recht, das hätte man durchaus tun können. Angesichts der knappen Zeit habe ich aber die in meinen Augen deutlich weniger aufwändige Alternative mit C-Strings für die wenigen Stellen, an der dies notwenig ist bevorzugt, anstatt ein komplettes Framework zu schreiben, welches schliessch an 1, 2 Stellen im Programm benutzt wird.
Ich zweifle sehr stark daran, dass dies der weniger aufwendigere Weg gewesen ist. Auf den ersten Blick mag dies vielleicht stimmen, aber spätestens beim Zweiten solltest du erkennen, wie fehleranfällig solche C Konstrukte sein können. Vielleicht hast du ein bisschen weniger Aufwand zum Schreiben (wobei ich sogar dies bezweifle), dafür kannst du dir eine Menge Ärger zu einem späteren Zeitpunkt einholen. Dass du ein komplettes Framework dafür schreiben müsstest, ist theatralisch übertrieben.
Auch finde ich es irgendwie lustig, dass du auf die C++ Möglichkeiten verzichtest, C einsetzt, dann aus Sicherheitsgründen auf nicht standardisierte Funktionen wie
sprintf_s
setzt und am Ende damit noch in undefiniertes Verhalten reinrennstIshildur schrieb:
Und für die Zukunft gibt es noch einiges zu lernen
Wer kann das nicht von sich behaupten? :p
Ich natürlich ... zweifelst du das in etwa an?
Es war aber mehr im Sinne gemeint, dass du aus deinen Ergebnissen besser nicht all zu viele Schlüsse für die Zukunft in der Programmierung in C++ ziehen solltest. Du dich daher besser zu der Thematik mit zum Beispiel Fachliteratur informieren solltest.Grüssli
-
Ishildur schrieb:
Kannst du mir jetzt mal erklären, wieso DU uuuuuuunbedingt einen std::vector benutzen willst (und mich als völligen Idiot hinstellst, weil ich es nicht tue) wenn du die von der std::vector Klasse gegenüber einem nativen array erweiterte Funktionalität überhaupt nicht benutzt?
Weil deine Argumentation falsch ist. ob vector oder nicht, so eine funktionalität hat gekapselt zu sein. und deine argumentation mit allokationen ist ebenfalls falsch - denn es ist nicht notwendig hier allokationen zu haben, auch vector macht keine.
nur vector oder etwas entsprechendes würde hier eine menge code sparen. was wenn du plötzlich mehr draw jobs hast?
Ja da gebe ich dir völlig recht, das hätte man durchaus tun können. Angesichts der knappen Zeit habe ich aber die in meinen Augen deutlich weniger aufwändige Alternative mit C-Strings für die wenigen Stellen, an der dies notwenig ist bevorzugt, anstatt ein komplettes Framework zu schreiben, welches schliessch an 1, 2 Stellen im Programm benutzt wird.
eine klasse oder ein allokator, der aufwand sind vielleicht 30min.
ne ne, das zählt nicht.deine entscheidungen mögen ja vielleicht sinn machen - aber deine argumentation ist falsch.
-
Ok. Kannst du mal den Code zeigen, der aus der gemessenen Zeit die Frequenz für die Anzeige berechnet?
Besser nicht sonst werde ich hier noch mehr zusammengestaucht :p
Zu dem was Dravere dazu geschrieben hat möchte ich noch hinzufügen, dass ich den Sinn von Optimierungen fragwürdig finde, die dazu dienen, die Anzahl der berechneten, aber letztlich sowieso unsichtbaren Bilder von 440 auf 940 zu steigern
Naja, wenn ich sämtliche Komponenten zusammenfüge inklusive Physik und AI bin ich schon bei unter 100 fps, aber für die Performance Tests der einzelnen Komponenten schalte ich alle anderen zwischenzeitlich aus. Die Textengine arbeitet (wenn alles andere deaktiviert ist) mit den 1000 fps, aber auch nur dann, wenn ich nur eine enzige Schrift verwende. Muss ich während dem Rendern noch ein Texturwechsel vornehmen, sinkt die Framerate auch gleich wieder drastisch, weil ich es dann in zwei Render Calls aufteilen muss, wobei ich natürlich nach Textur gruppiere.
1000 Hz liegt mit Sicherheit weit jenseits der Abfragefrequenz von so ziemlich jedem Eingabegerät
Ich studiere den Schwerpunkt "Computer Perception & Virtual Reality" offenbar sind dann alle unsere Scripts fehlerhaft... :p
Gucks du hier: http://www.pc-cooling.de/Eingabegeraete/Maeuse/900500200/SPEEDLINK+Kudos+Gaming+Mouse,+black.htmlAuch finde ich es irgendwie lustig, dass du auf die C++ Möglichkeiten verzichtest, C einsetzt, dann aus Sicherheitsgründen auf nicht standardisierte Funktionen wie sprintf_s setzt und am Ende damit noch in undefiniertes Verhalten reinrennst
Jaja, das findest du jetzt lustig was du Assi :p
-
Ishildur schrieb:
Ok. Kannst du mal den Code zeigen, der aus der gemessenen Zeit die Frequenz für die Anzeige berechnet?
Besser nicht sonst werde ich hier noch mehr zusammengestaucht :p
Dann vielleicht als genereller Tipp: Zeig zusätzlich zu den FPS auch die Framedauer in ms an, bis auf 2 Stellen hinter dem Komma (sollte mit PerformanceCounter ja kein Problem sein) und benutze diese Zahl für Vergleiche. FPS sind irreführend, weil bei 1000 FPS beispielsweise 0.5 ms Mehraufwand als dramatischer Verlust von 333 FPS dargestellt werden. Bei 60 FPS wären das gerade mal 2 Frames weniger. Und Rundungsfehler bei der Umrechnung können auch eine erhebliche Abweichung verursachen.
1000 Hz liegt mit Sicherheit weit jenseits der Abfragefrequenz von so ziemlich jedem Eingabegerät
Ich studiere den Schwerpunkt "Computer Perception & Virtual Reality" offenbar sind dann alle unsere Scripts fehlerhaft... :p
Gucks du hier: http://www.pc-cooling.de/Eingabegeraete/Maeuse/900500200/SPEEDLINK+Kudos+Gaming+Mouse,+black.htmlOk, ich erkenne die Existenz dieser "Gaming Mouse" an, die 1000 Hz polling rate verspricht. Was diese Werbeaussauge in der Realität wert ist, kann ich nicht beurteilen. Und übliches Equipment dürfte erheblich langsamer abgefragt werden.
-
@Shade of Mine
denn es ist nicht notwendig hier allokationen zu haben, auch vector macht keine.std::vector<int> lsInt; int index = 0;
int aInt[MAX_TEXT]; int index = 0;
Wo ist jetzt der Unterschied? Das std::vector selbstständig wächst? Ja aber nicht wenn ich den [] operator von std::vector benutze um daraum zuzugreifen. Damit std::vector wächst muss ich Add benutzen. Und wenn ich Add benutze muss ich doch auch Clear benutzten?? Natürlich, im einfachsten Fall setzt Clear einfach den internen AddZeiger wieder auf 0, aber eben man weiss nicht so genau was das Ding dann wirklich macht? Bei einem nativen array weiss ich hingegen genau was ich mache. Zusätzlich wird einfach von Vector jedes Mal, wenn ich diese Methode aufrufe ein new und ein delete erzeugt. Während das native Array einfach ein sub esp MAX_TEXT macht? Was wird wohl schneller sein?
eine klasse oder ein allokator, der aufwand sind vielleicht 30min.
Ein Memorypool Manager, der sämtliche Instancen informieren muss, wenn eine Reallokation auf dem Heap stattgefunden hat programmierst du in 30min?