fprintf - Zugriffsverletzung

  • C++/CLI

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Elanda.

    fprintf - Zugriffsverletzung

    Hallo zusammen,

    ich bin gerade dabei eine Logfile Klasse zu schreiben, die mir Meldungen im html Format ausgibt.

    Die Datei wird erstellt, und die ersten Daten werden in die Datei geschrieben. Wenn ich dann weiteres in die Datei schreiben will bekomme ich folgende Meldung :

    Quellcode

    1. ​Ausnahme ausgelöst bei 0x774760C5 (ntdll.dll) in HTML Logfile 8.6.1.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x01010125.


    Wenn ich in Einzelschritten dem Programm Ablauf folge passiert der Fehler nach fopen_s(&m_LogFile, LogName, "a"); in der Funktion void CLogfile::Textout nach dem Erstellen der Überschrift, Email ect.

    Logfile Klasse
    Spoiler anzeigen
    ​CLogfile.cpp
    Spoiler anzeigen

    C-Quellcode

    1. #include "CLogfile.h"
    2. CLogfile::CLogfile() {
    3. m_LogFile = nullptr;
    4. }
    5. CLogfile::~CLogfile() {
    6. //Destruktor
    7. //Logfile Ende schreiben und Datei schließen
    8. Textout("<br><br>End of logfile</font></body></html>");
    9. fclose(m_LogFile);
    10. }
    11. void CLogfile::Textout(const char* Text) {
    12. fprintf(m_LogFile, Text);
    13. fflush(m_LogFile);
    14. }
    15. void CLogfile::CreateLogfile(const char* LogName) {
    16. //Logfile leeren und Kopf schreiben
    17. fopen_s(&m_LogFile, LogName, "w");
    18. Textout("<html><head><title>Logfile</title></head>");
    19. Textout("<bod><font face='courier new'>");
    20. WriteTopic("Logfile", 3);
    21. #ifdef _DEBUG
    22. Textout("BUILD: DEBUG <br>");
    23. #else
    24. Textout("BUILD: RELEASE<br>");
    25. #endif // _DEBUG
    26. Textout("<a href='mailto:hiermaileinfuegen@gmail.com?subject=Logfile'>");
    27. Textout("Send E-Mail to me</a><br><br>");
    28. //Logfile schließen und mit append wieder öffnen
    29. fclose(m_LogFile);
    30. fopen_s(&m_LogFile, LogName, "a");
    31. }
    32. void CLogfile::WriteTopic(const char* Topic, int size) {
    33. //Überschrift schreiben und flushen
    34. Textout("<table cellspacing='0' cellpadding='0' width = '100%%' ");
    35. Textout("bgcolor='#DFDFE5'>\n<tr>\n<td>\n<font face='arial' ");
    36. fTextout("size='+%i'>\n", size);
    37. Textout(Topic);
    38. Textout("</font>\n</td>\n</tr>\n</table>\n<br>");
    39. fflush(m_LogFile);
    40. }
    41. void CLogfile::Textout(int color, const char* Text) {
    42. Textout(color, false, Text);
    43. }
    44. void CLogfile::Textout(int color, bool List, const char* Text) {
    45. //Listentag schreiben
    46. if (List == true) {
    47. Textout("<li>");
    48. }
    49. //Farbtag schreiben
    50. switch (color)
    51. {
    52. case BLACK:
    53. Textout("<font color=black>"); break;
    54. case RED:
    55. Textout("<font color=red>"); break;
    56. case GREEN:
    57. Textout("<font color=green>"); break;
    58. case BLUE:
    59. Textout("<font color=blue>"); break;
    60. case PURPLE:
    61. Textout("font color=purple>"); break;
    62. };
    63. Textout(Text);
    64. Textout("</font>");
    65. if (List == false) {
    66. Textout("<br>");
    67. }
    68. else {
    69. Textout("</li>");
    70. }
    71. }
    72. void CLogfile::fTextout(const char *Text, ...) {
    73. CHAR buffer[MAX_BUFFER];
    74. va_list pArgList;
    75. va_start(pArgList, Text);
    76. vsprintf_s (buffer, Text, pArgList);
    77. va_end(pArgList);
    78. Textout(buffer);
    79. }
    80. void CLogfile::fTextout(int Color, const char *Text, ...) {
    81. CHAR buffer[MAX_BUFFER];
    82. va_list pArgList;
    83. va_start(pArgList, Text);
    84. vsprintf_s(buffer, Text, pArgList);
    85. va_end(pArgList);
    86. Textout(Color, buffer);
    87. }
    88. void CLogfile::fTextout(int color, bool List, const char* Text, ...) {
    89. CHAR buffer[MAX_BUFFER];
    90. va_list pArgList;
    91. va_start(pArgList, Text);
    92. vsprintf_s(buffer, Text, pArgList);
    93. va_end(pArgList);
    94. Textout(color, List, buffer);
    95. }
    96. void CLogfile::FunctionResult(const char* Name, bool Result) {
    97. if (L_OK == Result) {
    98. Textout("<table width='100%%' cellSpacing='1' cellPadding='5'");
    99. Textout(" border='0' bgcolor='#C0C0C0C0'><tr><td bgcolor=");
    100. fTextout("'#FFFFFF' width='35%%'>%s</TD>", Name);
    101. Textout("'green'>OK</FONT></TD><td bgcolor='#FFFFFF' ");
    102. Textout("width='35%%'>-/-</TD></tr></table>");
    103. }
    104. else {
    105. Textout("<table width='100%%' cellSpacing='1' cellPadding='5'");
    106. Textout(" border='0' bgcolor='#C0C0C0C0'><tr><td bgcolor=");
    107. fTextout("'#FFFFFF' width='35%%'>%s</TD>", Name);
    108. Textout("'red'>ERROR</FONT></TD><td bgcolor='#FFFFFF' ");
    109. Textout("width='35%%'>-/-</TD></tr></table>");
    110. }
    111. }

    CLogfile.h
    Spoiler anzeigen

    C-Quellcode

    1. ​#pragma once
    2. #ifndef __CLOGFILE
    3. #define __CLOGFILE
    4. #include <Windows.h>
    5. #include <stdio.h>
    6. #include "Singleton.h"
    7. constexpr auto MAX_BUFFER = 1024;
    8. constexpr auto L_FAIL = false;
    9. constexpr auto L_OK = true;
    10. #define g_pLogFile CLogfile::Get()
    11. enum FONTCOLORS {
    12. BLACK,
    13. RED,
    14. GREEN,
    15. BLUE,
    16. PURPLE
    17. };
    18. class CLogfile : public Singleton<CLogfile>
    19. {
    20. public:
    21. CLogfile();
    22. ~CLogfile();
    23. void CreateLogfile(const char *LogName);
    24. void WriteTopic(const char *topic, int size);
    25. void Textout(const char *Text);
    26. void Textout(int Color, const char *Text);
    27. void Textout(int color, bool List, const char *Text);
    28. void fTextout(const char *Text, ...);
    29. void fTextout(int color, const char *Text,...);
    30. void fTextout(int color, bool List, const char* Text, ...);
    31. void FunctionResult(const char* Name, bool Result);
    32. private:
    33. FILE* m_LogFile;
    34. };
    35. #endif // !__CLOGFILE



    Singleton Klasse
    Spoiler anzeigen

    C-Quellcode

    1. #pragma once
    2. #ifndef SINGLETON
    3. #define SINGLETON
    4. template <class T>
    5. class Singleton
    6. {
    7. protected:
    8. static T* m_pSignleton;
    9. public:
    10. virtual ~Singleton() {};
    11. inline static T* Get() {
    12. if (!m_pSignleton) {
    13. m_pSignleton = new T;
    14. return (m_pSignleton);
    15. }
    16. }
    17. static void Del() {
    18. if (m_pSignleton) {
    19. delete (m_pSignleton);
    20. m_pSignleton = nullptr;
    21. }
    22. }
    23. };
    24. // Die Statische Variabel erzeugen
    25. template<class T>
    26. T* Singleton<T>::m_pSignleton = nullptr;
    27. #endif


    C-Quellcode

    1. int main()
    2. {
    3. g_pLogFile->CreateLogfile("Logfilke.html"); // <- Erstellt die Datei, und die ersten Daten wie überschrift, Email, Debug ect.
    4. g_pLogFile->Textout("Hi"); //<- nope
    5. }


    Der letzte Abschnitt bei der Logfile Klasse die, die Datei erstellt endet mit :

    C-Quellcode

    1. ​fclose(m_LogFile);
    2. fopen_s(&m_LogFile, LogName, "a");


    Der Stream sollte geschlossen werden und im Append Modus wieder geöfnnet werden. Beim erneuten schreiben passiert es.

    Hoffe ihr könnt mir weiter helfen. lg
    Bilder
    • Screenshot_2.png

      16,52 kB, 491×235, 77 mal angesehen

    Farliam schrieb:

    Zugriffsverletzung beim Schreiben an Position 0x01010125
    Ist das reproduzierbar?
    Ist das Laufwerk voll?
    Kann es sein, dass es für die Datei eine Größenbeschränkung gibt?
    ====
    Warum C++?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nach erneutem starten von Visual Studio ist die Adresse anders : 0x774760C5
    Aber beim Debuggen immer die selbe Adresse.

    Das Laufwerk hat Platz ohne Ende.
    Größenbeschränkung? Die Datei wird geschlossen und im Append Modus wieder geöffnet. Alle Daten die danach folgen, sollten an das Ende der Datei angehängt werden.
    Warum? Weil es mir Spaß macht, mal etwas neues kennen zu lernen :)
    Welches Studio verwendest Du?
    Das würde ich gern mal nachvollziehen.
    Kannst Du das bereinigte Projekt anhängen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Farliam bereinigen heißt, dass (fast) alle Dateien, die das Studio selbst erstellen kann, gelöscht werden, um das ZIP schmal zu halten:

    Ich hoffe, dass es das bei CLI auch gibt.
    Ich hab das 17er Studio, mal sehen.
    =====
    Fehler im Code:

    C-Quellcode

    1. inline static T* Get()
    2. {
    3. if (!m_pSignleton)
    4. {
    5. m_pSignleton = new T;
    6. }
    7. return (m_pSignleton); // dies aus dem If-Block rausgeholt
    8. }
    =====
    Was muss ich tun, um den Fehler zu reproduzieren?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „RodFromGermany“ ()

    RodFromGermany schrieb:

    return (m_pSignleton); // dies aus dem If-Block rausgeholt


    Schande über mich :D Ich war so fixiert auf die Logfile Klasse, dass ich der Basisklasse gar keine Beachtung geschenkt habe. Deswegen hat es auch beim ersten mal funktioniert, als der Singelton noch 0 war. Nach dem initialisieren bei der 2ten Abfrage kam bei GET nichts mehr zurück. Wie bist du darauf gekommen?

    Einfach durch´s optische nachschauen, oder über den Debugger und Einzelschritten?

    Nochmal vielen dank.

    Farliam schrieb:

    Wie bist du darauf gekommen?[/quote='Studio']

    Studio schrieb:

    Quellcode

    1. 1>c:\temp\_müll\htmllogfile\html logfile 8.6.1\singleton.h(21): warning C4715: "Singleton<CLogfile>::Get": Nicht alle Codepfade geben einen Wert zurück.
    War es das?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Schmeiß mal den ganzen C-Müll da raus. Ich bin mir nicht sicher ob ein singleton als Design sinnvoll ist. Man erreicht nämlich mit einem globalen std::ofstream Objekt das gleiche. Ich hab dir trotzdem mal ein einfaches Beispiel gemacht:
    Spoiler anzeigen

    C-Quellcode

    1. class logfile
    2. {
    3. public:
    4. logfile(const logfile&) = delete;
    5. static logfile& get()
    6. {
    7. if (instance.get() == nullptr)
    8. instance = std::unique_ptr<logfile>(new logfile());
    9. return *instance.get();
    10. }
    11. void open(const std::string& filename) { textfile = std::ofstream(filename); }
    12. void close() { textfile.close(); }
    13. template <typename t>
    14. std::ostream& operator<<(const t& t_)
    15. {
    16. return textfile << t_;
    17. }
    18. private:
    19. static std::unique_ptr<logfile> instance;
    20. std::ofstream textfile;
    21. logfile() {}
    22. };
    23. std::unique_ptr<logfile> logfile::instance = std::unique_ptr<logfile>();
    24. int main()
    25. {
    26. logfile::get().open(R"(Pfad entfernt^^)");
    27. logfile::get() << "Hallo " << 45327 << "Welt!" << std::endl;
    28. }

    Wenn du dazu Fragen hast, einfach fragen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gonger96“ ()

    Gonger96 schrieb:

    Schmeiß mal den ganzen C-Müll da raus. Ich bin mir nicht sicher ob ein singleton als Design sinnvoll ist. Man erreicht nämlich mit einem globalen std::ofstream Objekt das gleiche. Ich hab dir trotzdem mal ein einfaches Beispiel gemacht:


    Muss gestehen ich bin erst seit 1 Woche dabei. Und lerne, wie wir schon aus meinem anderen Post gemerkt haben, scheinbar von einem inhaltlich Uralt Buch.

    Gonger96 schrieb:

    C-Quellcode

    1. template <typename t>
    2. std::ostream& operator<<(const t& t_)
    3. {
    4. return textfile << t_;
    5. }


    Werden dort die << überladen und als Template deklariert?

    Wie kann ich außerdem alten C von neuen C++ Code unterscheiden?

    Ich hab 3 Bücher zur Auswahl, die ich eigentlich nacheinander durchgehen wollte :







    @Gonger96 Welches würdest du mir empfehlen, mit dem ich weitermachen sollte?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Farliam“ ()

    Jo der << Operator wird überladen und dient als Wrapper für den ofstream operator <<. Es ist ein Template damit alle Typen unterstützt werden, die ofstream unterstützt.

    Alles was in irgendwelchen Windows Headern ist, ist kein Standard C++ bzw. gehört nicht zur Standardbibliothek. Ansonsten enden C-Std Header immer auf .h während C++ Standard Header keine Endung haben. Hier ist übrigens eine gute Doku.
    1.Kein muss, aber ein Tipp.
    Im Falle eines Singleton geht es noch viel einfacher und du ersparst dir auch den heap-speicher.

    Sieht dann ungefähr so aus:

    C-Quellcode

    1. static Logfile& get()
    2. {
    3. static Logfile log;
    4. return log;
    5. }


    Sieht nebenbei auch viel schöner aus und liest sich auch besser.

    2. Bei dem << operator overload empfehle ich dir das hier zu machen.

    C-Quellcode

    1. template<class T>
    2. std::ostream& operator<<(T value)
    3. {
    4. return textfile << value;
    5. }


    Die const reference kannst du dir sparen, da der größte Typ der von std::ostream akzeptiert wird sowieso nur 64 bit groß ist. (Zumindest auf Windows, und es ist sowieso warscheinlichicher Datentypen zu übergeben die kleiner sind.)
    Während mit einer Referenz (wenn die Funktion nicht sowieso inlined wird) immer 64 bit übergeben werden.
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------