LoadString-Problem



  • Hallo an alle,

    ich habe ein Problem mit LoadString. Und zwar, wenn ich folgendes mache funktioniert alles wunderbar:

    // MyDLL ist so definiert: MyDLL = LoadLibrary("mydll.dll");
    
    char buf[256];
    LoadString(MyDLL,IDS_ERROR_ACCFILE_NOT_FOUND,buf,sizeof(buf));
    
    MessageBox(NULL,buf,"",0);
    

    Doch, wenn ich das in eine Funktion packe, dann bekomme ich einen leeren String:

    char *LoadStringFromRes(HINSTANCE Module, int ID)
    {
        char buffer[256] = "";
        LoadString(Module,ID,buffer,256);
        return buffer;
    }
    
    MessageBox(NULL, LoadStringFromRes(MyDLL, IDS_TEST), "", 0); // Leerer String
    

    Ich bedanke mich im Voraus für jeden Tip!!

    mfg
    Mister X



  • IDS_TEST != IDS_ERROR_ACCFILE_NOT_FOUND.

    Sollte das ein Flüchtigskeitsfehler im Posting sein, leigt es daran, dass buffer nach Beenden der Funktion freigegeben wird. Damit ist das Verhalten undefiniert, auch wenn es ungewöhnlich ist, dass reproduzierbar in genau dem Moment der Speicher überschrieben wird.



  • Erstmal Danke für deine Antwort!!
    Ja, das ist ein Fehler im Posting (also nicht in meinem Prog). (Habe keinen Editier-Button gefunden)

    Und wie verhindert man jetzt, dass buffer freigegeben wird? Bzw. gibt es eine andere Möglichkeit dies zu realisieren?



  • (Habe mich jetzt registriert. Also ich ComFreek=Mister 😵



  • Mister X schrieb:

    Und wie verhindert man jetzt, dass buffer freigegeben wird? Bzw. gibt es eine andere Möglichkeit dies zu realisieren?

    Man muss den Buffer dynamisch anfordern:

    char *LoadStringFromRes(HINSTANCE Module, int ID)
    {
        char buffer = new char[256];
        LoadString(Module,ID,buffer,256);
        return buffer;
    }
    
    char* text = LoadStringFromRes(MyDLL, IDS_ERROR_ACCFILE_NOT_FOUND_TEST)
    MessageBox(NULL, text, "", 0);
    
    delete[] text; // nicht vergessen!
    

    Nachteil ist, dass man außerhalb der Funtkion den Speicher freigeben muss, sonst entstehen Leaks. Das wird im allgemeinen als sehr unsauberer Stil angesehen.

    Im Prinzip müsste man es so lösen, dass LoadStringFromRes den buffer als Parameter nimmt und dann befüllt, also:

    void LoadStringFromRes(HINSTANCE Module, int ID, char *buffer, size_t size)
    {
        LoadString(Module,ID,buffer,size);
    }
    
    char buffer[256];
    LoadStringFromRes(MyDLL, IDS_ERROR_ACCFILE_NOT_FOUND_TEST, buffer, 256)
    MessageBox(NULL, buffer, "", 0);
    

    Hier ist Speicheranforderung und -freigabe nicht auseinandergerissen wie oben. Aber wie man sieht, hat man damit aber nicht viel gekonnt.

    Eine viel bessere Möglichkeit ist, mit std::string zu arbeiten:

    std::string LoadStringFromRes(HINSTANCE Module, int ID)
    {
        char buffer[256];
        LoadString(Module,ID,a.get(),256);
        return std::string(buffer);
    }
    
    MessageBox(NULL, LoadStringFromRes(MyDLL, IDS_ERROR_ACCFILE_NOT_FOUND_TEST).c_str(), "", 0);
    
    // alternativ:
    std::string s = LoadStringFromRes(MyDLL, IDS_ERROR_ACCFILE_NOT_FOUND_TEST);
    MessageBox(NULL, s.c_str(), "", 0);
    

    (Ich bin mir jetzt nicht 100%-ig sicher, ob der Standard garantiert, dass der zurückgegebene std::string im 1. Fall erst zerstört wird, wenn der komplette Ausdruck ausgewertet ist, meine Tests deuten aber darauf hin.)

    Ansonsten, wenn das der einzige Fall wäre, wäre vielleicht auch eine Funktion MessageBoxWithStringFromRes o.ä. denkbar.



  • Danke für deine Antwort.
    Aber bei deinem 3.Beispiel woher hast du std::string a. Außerdem gibt es keine Methode get, wahrscheinlich meintest du a.data(). Ich habe es jetzt so probiert:

    std::string LoadStringFromRes(HINSTANCE Module, int ID)
    {
        std::string a;
        LoadString(Module, ID, const_cast<char*>(a.data()), 256);  // Sind 256 richtig?
        return a;
    }
    
    MessageBox(NULL, LoadStringFromRes(MyDLL, IDS_ERROR_ACCFILE_NOT_FOUND), "", 0);
    

    Wie du gesagt hast, ist das eine sichere Methode, damit keine Speicherlecks entstehen?


Anmelden zum Antworten