Ich hoffe, diese Frage ist nicht zu offen. Ich stieß auf ein Speicherproblem mit Rust, wo ich an "out of memory" from calling next
on an Iterator
trait object bekam. Ich bin mir nicht sicher, wie ich es debuggen soll. Drucke haben mich nur zu dem Punkt gebracht, an dem der Fehler auftritt. Ich bin nicht sehr vertraut mit anderen Tools wie ltrace, also obwohl ich eine Spur erstellen konnte (231MiB, pff), wusste ich nicht wirklich was damit zu tun. Ist eine solche Spur nützlich? Würde ich besser gdb/lldb greifen? Oder Valgrind?Wie kann ich ein Speicherproblem in Rust debuggen?
Antwort
Im Allgemeinen würde ich versuchen, den folgenden Ansatz zu tun:
Boilerplate-Reduktion: Versuchen Sie, das Problem der OOM zu verengen, so dass Sie um zusätzlichen Code nicht zu viel haben. Mit anderen Worten: Je schneller Ihr Programm abstürzt, desto besser. Manchmal ist es auch möglich, ein bestimmtes Stück Code herauszureißen und für die Untersuchung in eine extra Binärdatei zu schreiben.
Problem Größenreduktion: Senken Sie das Problem von OOM zu einem einfachen „zu viel Speicher“, so dass Sie die einige Teil Abfälle etwas, aber eigentlich sagen kann, dass es zu einem OOM führt nicht. Wenn es zu schwierig ist zu sagen, ob das Problem auftritt oder nicht, können Sie das Speicherlimit verringern.
Versammlungulimit -Sv 500000 # that's 500MB ./path/to/exe --foo
Informationen:: Unter Linux können diese
ulimit
verwenden getan werden Wenn Sie Problem klein genug ist, sind Sie bereit, Informationen zu sammeln, die einen niedrigeren Geräuschpegel aufweist. Es gibt mehrere Möglichkeiten, die Sie ausprobieren können. Denken Sie daran, Ihr Programm mit Debug-Symbolen zu kompilieren. Es kann auch ein Vorteil sein, die Optimierung auszuschalten, da dies normalerweise zu einem Informationsverlust führt. Beide können archiviert werden, indem das Flag--release
während der Kompilierung NICHT verwendet wird.Heap Profilierung: Ein Weg zu gperftools ist zu verwenden:
LD_PRELOAD="/usr/lib/libtcmalloc.so" HEAPPROFILE=/tmp/profile ./path/to/exe --foo pprof --gv ./path/to/exe /tmp/profile/profile.0100.heap
Dies zeigt Ihnen ein Diagramm, das symbolisiert, welche Teile des Programms essen, die Menge an Speicher. Weitere Informationen finden Sie unter official docs.
rr: Manchmal ist es sehr schwierig herauszufinden, was tatsächlich passiert, besonders nachdem Sie ein Profil erstellt haben. Vorausgesetzt, dass Sie in Schritt 2 einen guten Job, können Sie rr verwenden:
rr record ./path/to/exe --foo rr replay
Dies wird eine GDB mit Supermächten laichen. Der Unterschied zu einer normalen Debug-Sitzung ist, dass Sie nicht nur
continue
, sondern auchreverse-continue
. Grundsätzlich wird Ihr Programm von einer Aufnahme ausgeführt, bei der Sie beliebig vor- und zurückspringen können. This wiki page bietet Ihnen einige zusätzliche Beispiele. Eine Sache, die darauf hinweist, ist, dass rr nur mit GDB zu arbeiten scheint.Gutes altes Debugging: Manchmal bekommen Sie Spuren und Aufnahmen, die immer noch viel zu groß sind. In diesem Fall können Sie (in Kombination mit dem
ulimit
Trick) nur GDB benutzen und warten, bis das Programm abstürzt:gdb --args ./path/to/exe --foo
Sie sollen nun eine normale Debug-Sitzung, wo Sie, was der aktuelle Stand des Programms untersuchen war . GDB kann auch mit Coredumps gestartet werden. Das allgemeine Problem bei diesem Ansatz besteht darin, dass Sie nicht rechtzeitig zurückgehen können und Sie nicht mit der Ausführung fortfahren können. Sie sehen also nur den aktuellen Status einschließlich aller Stack-Frames und Variablen. Hier könnten Sie auch LLDB verwenden, wenn Sie möchten.
(Potential) fix + repeat: Nachdem Sie einen Klebstoff, was Sie könnte schief gehen kann versuchen, den Code zu ändern. Dann versuche es noch einmal. Wenn es immer noch nicht funktioniert, gehen Sie zurück zu Schritt 3 und versuchen Sie es erneut.
Im Allgemeinen können Sie zum Debuggen entweder einen protokollbasierten Ansatz verwenden (entweder durch Einfügen der Protokolle selbst oder mit einem Tool wie ltrace
, ptrace
, ... um die Protokolle für Sie zu generieren) oder Sie können Verwenden Sie einen Debugger.
Beachten Sie, dass ltrace
, ptrace
oder Debugger-basierte Ansätze erfordern, dass Sie das Problem reproduzieren können; Ich bevorzuge manuelle Protokolle, da ich in einer Branche arbeite, in der Fehlerberichte im Allgemeinen zu ungenau sind, um eine sofortige Reproduktion zu ermöglichen (und daher verwenden wir Protokolle, um das Reproduzier-Szenario zu erstellen).
Rust unterstützt beide Ansätze, und das Standard-Toolset, das für C- oder C++ - Programme verwendet wird, funktioniert gut.
Mein persönlicher Ansatz ist einige Anmeldung an Ort und Stelle, um schnell einzugrenzen, wo das Problem auftritt, und wenn die Protokollierung nicht ausreicht, um einen Debugger für eine feinere Prüfung zu starten. In diesem Fall würde ich empfehlen, sofort zum Debugger zu gehen.
Es wird panic
generiert, was bedeutet, dass Sie beim Aufrufen des Call Hooks sowohl den Call Stack als auch den Speicherstatus sehen können, wenn etwas schief läuft.
Starten Sie Ihr Programm mit dem Debugger, setzen Sie einen Breakpoint auf den Panikhaken, führen Sie das Programm, profitieren.
- 1. Wie kann ich ein Schwein Skript debuggen
- 2. Wie kann ich ein * Char über FFI in Rust freigeben?
- 3. Debuggen eines Stack-Überlaufs in Rust
- 4. Python - Speicherproblem
- 5. Wie kann ich in IntelliJ ein Maven-Testziel debuggen?
- 6. Wie kann ich ein Juwel in Rails debuggen?
- 7. Kann ich Module "seitlich" in Rust einbauen?
- 8. Wie kann ich einen fehlgeschlagenen Frachttest in gdb debuggen?
- 9. Wie kann ich beim Debuggen von MSVC ABI Rust-Programmen Variablenwerte prüfen?
- 10. Wie kann ich in RSpec besser debuggen?
- 11. Wie kann ich PHP in IIS debuggen?
- 12. Wie kann ich Regex in Rust ohne Fracht verwenden?
- 13. Wie kann ich ein PHP-CLI-Skript mit xdebug debuggen?
- 14. Kann ein Rust-Makro neue Kennungen erstellen?
- 15. Wie benutze ich externe Kisten in Rust?
- 16. Wie kann ich ein Programm mit scanf mit DDD debuggen?
- 17. FlowDocument Speicherproblem in C#
- 18. In Rust, ist ein Vektor ein Iterator?
- 19. Wie mache ich Echtzeit-Programmierung in Rust?
- 20. Wie kann ich in Rust 1.0 eine Zufallszahl erhalten?
- 21. Wie kann ich die Zuweisungsoperation in Rust überladen?
- 22. Wie kann ich wissen, ob in Rust etwas initialisiert wird?
- 23. Wie kann ich Dateien eines Verzeichnisses in Rust auflisten?
- 24. Speicherproblem in ARC
- 25. Wie kann ich einen benutzerdefinierten Debugger debuggen?
- 26. Wie bekomme ich Feldnamen in Rust?
- 27. Wie lagere ich eine Schließung in Rust?
- 28. Wie kann ich fehlerhafte Soap-Anfragen debuggen?
- 29. MPMoviePlayerViewController Speicherproblem
- 30. Wie kann ich einen benutzerdefinierten Transformator debuggen
Valgrind ist immer ein guter Anfang. Versuchen Sie auch, Ihren Code zu optimieren. –
@EliSadoff Wie hilft die Optimierung meines Codes beim Debugging von Speicherproblemen? – Apanatshka