LPWSTR mit malloc Problem



  • Hallo,

    ich hab ein Problem an dem ich absolut nicht weiterkomme.
    Der Code lässt sich kompilieren, tut aber nicht das was er soll.
    Der Inhalt der Messageboxen in strcatW stimmt, wenn ich dann aber außerhalb der Funktion mir den Pointer (lpszwModuleInfo) anzeigen lasse kommt nichts!

    #include <windows.h>
    
    BOOL strcatW( LPWSTR lpszwRoot, LPCWSTR lpszwCat, LPCWSTR lpszwAdditional )
    {
    	LPWSTR	lpszwTemp	= NULL;
    
    	if( lpszwRoot == NULL )
    	{
    		if( lpszwCat != NULL )
    		{
    			if( lpszwAdditional != NULL )
    			{
    				// NULL, Pointer, L"Example"
    				lpszwRoot = (LPWSTR) malloc((wcslen(lpszwCat) + wcslen(lpszwAdditional)) * sizeof(wchar_t));
    				if( lpszwRoot  == NULL )
    					return FALSE;
    
    				wcscpy( lpszwRoot, lpszwCat );
    				wcscat( lpszwRoot, lpszwAdditional );
    				MessageBoxW( NULL, lpszwRoot, L"NULL,Pointer,Example", MB_OK ); 
    				return TRUE;
    			}
    			else
    			{
    				// NULL, Pointer, NULL
    				lpszwRoot = (LPWSTR) malloc((wcslen(lpszwCat) * sizeof(wchar_t)));
    				if( lpszwRoot == NULL )
    					return FALSE;
    
    				wcscpy( lpszwRoot, lpszwCat );
    				MessageBoxW( NULL, lpszwRoot, L"NULL,Pointer,NULL", MB_OK ); 
    				return TRUE;
    			}
    		}
    		else
    		{
    			if( lpszwAdditional != NULL )
    			{
    				// NULL, NULL, L"Example"
    				lpszwRoot = (LPWSTR) malloc((wcslen(lpszwCat) + wcslen(lpszwAdditional)) * sizeof(wchar_t));
    				if( lpszwRoot == NULL )
    					return FALSE;
    
    				wcscpy( lpszwRoot, lpszwAdditional );
    				MessageBoxW( NULL, lpszwRoot, L"NULL,NULL,Example", MB_OK ); 
    				return TRUE;
    			}
    			else
    				// NULL, NULL, NULL
    				return FALSE;
    		}
    	}
    	else
    	{
    		if( lpszwCat != NULL )
    		{
    			if( lpszwAdditional != NULL )
    			{
    				// Pointer, Pointer, L"Example"
    				lpszwTemp = (LPWSTR) malloc(wcslen(lpszwRoot) * sizeof(wchar_t));
    				if( lpszwTemp = NULL )
    					return FALSE;
    
    				wcscpy( lpszwTemp, lpszwRoot );
    				GlobalFree( lpszwRoot );
    
    				lpszwRoot = (LPWSTR) malloc((wcslen(lpszwTemp) + wcslen(lpszwCat) + wcslen(lpszwAdditional)) * sizeof(wchar_t));
    				if( lpszwRoot == NULL )
    					return FALSE;
    
    				wcscpy( lpszwRoot, lpszwTemp );
    				wcscat( lpszwRoot, lpszwCat );
    				wcscat( lpszwRoot, lpszwAdditional );
    				MessageBoxW( NULL, lpszwRoot, L"Pointer,Pointer,Example", MB_OK ); 
    				GlobalFree( lpszwTemp );
    				return TRUE;
    			}
    			else
    			{
    				// Pointer, Pointer, NULL
    				lpszwTemp = (LPWSTR) malloc(wcslen(lpszwRoot) * sizeof(wchar_t));
    				if( lpszwTemp = NULL )
    					return FALSE;
    
    				wcscpy( lpszwTemp, lpszwRoot );
    				GlobalFree( lpszwRoot );
    
    				lpszwRoot = (LPWSTR) malloc((wcslen(lpszwTemp) + wcslen(lpszwCat)) * sizeof(wchar_t));
    				if( lpszwRoot == NULL )
    					return FALSE;
    
    				wcscpy( lpszwRoot, lpszwTemp );
    				wcscat( lpszwRoot, lpszwCat );
    				MessageBoxW( NULL, lpszwRoot, L"Pointer,Pointer,NULL", MB_OK ); 
    				GlobalFree( lpszwTemp );
    				return TRUE;
    			}
    		}
    		else
    		{
    			if( lpszwAdditional != NULL )
    			{
    				// Pointer, NULL, L"Example"
    				lpszwTemp = (LPWSTR) malloc(wcslen(lpszwRoot) * sizeof(wchar_t));
    				if( lpszwTemp = NULL )
    					return FALSE;
    
    				wcscpy( lpszwTemp, lpszwRoot );
    				GlobalFree( lpszwRoot );
    
    				lpszwRoot = (LPWSTR) malloc((wcslen(lpszwTemp) + wcslen(lpszwAdditional)) * sizeof(wchar_t));
    				if( lpszwRoot == NULL )
    					return FALSE;
    
    				wcscpy( lpszwRoot, lpszwTemp );
    				wcscat( lpszwRoot, lpszwAdditional );
    				MessageBoxW( NULL, lpszwRoot, L"Pointer,NULL,Example", MB_OK ); 
    				GlobalFree( lpszwTemp );
    				return TRUE;
    			}
    			else
    				// Pointer, NULL, NULL
    				return TRUE;
    		}
    	}
    }
    
    int main(void)
    {
        LPWSTR    lpszwModuleInfo     = NULL;
    
        if( !strcatW( lpszwModuleInfo, L"Test", NULL ))
        {
            MessageBox( NULL, "Fehler strcatW", "Fehler", MB_OK );
            return 0;
        }
        else MessageBoxW( NULL, lpszwModuleInfo, L"Modulinfo", MB_OK );
    
        return 0;
    }
    

    Wäre super wenn sich das mal einer anschauen könnte.

    MfG
    unicode frager



  • 1. Du musst bei malloc als Parameter "(stringlänge + 1) * sizeof(WCHAR)" angeben, da die Strings nullterminiert sind.
    2. 'lpszwRoot' ist eine lokale Variable und verändert nicht den ursprünglichen Pointer, der an strcatW übergeben wurde.



  • Hallo Neku,

    irgendwie sowas hab ich mir schon gedacht. Wie kann ich jetzt lpszwModuleInfo auf die lokale Variable lpszwRoot "angleichen"?

    MfG
    unicode frager



  • Wer heute noch mit wchar_t*/char* arbeitet ist selber schuld...
    Verwendet bitte CString (MFC) oder std::string/wstring (ohne MFC).
    Damit sparst Du Dir ganz viele selbstgemachte Probleme.



  • Jochen Kalmbach schrieb:

    Wer heute noch mit wchar_t*/char* arbeitet ist selber schuld...
    Verwendet bitte CString (MFC) oder std::string/wstring (ohne MFC).
    Damit sparst Du Dir ganz viele selbstgemachte Probleme.

    Soweit ich das sehe verwendet er doch C und nicht C++.

    @unicode frager: Du kannst entweder die neue Speicheradresse zurückgeben lassen (und NULL, falls ein Problem auftrat) - oder aber du übergibst ein LPWSTR*, also einen Pointer auf einen wchar_t-Pointer, welchen du dann ändern kannst.



  • Danke mal für die Antworten.

    Ich benutze im Grunde ein Mischmasch von C und C++ in meinem Programm. Die std::string Funktionen sind schon praktisch, lassen mein Programm aber gleich mal 50kB größer werden. Und wenn ich dann auch noch die stringstream Funktionen nutzen will, sind es noch mal gut 250kB mehr! Wenn du was kleineres zur Verfügung hättest, gerne 🙂



  • Was sind 50 KB? Und warum willst Du stringstream? wenn Du bisher auch ohne ausgekommen bist?



  • Jochen Kalmbach schrieb:

    Was sind 50 KB?

    Mein Programm wird eine Library für andere Programme, da kommt es schon etwas auf die Größe drauf an.

    Jochen Kalmbach schrieb:

    Und warum willst Du stringstream? wenn Du bisher auch ohne ausgekommen bist?

    Ich hab öfters sprintf in meinem Programm, wenn ich nun mit strings arbeite muss ich die ja erst wieder umständlich zu const char* umwandlen und zurück, da ist die stringstream lib doch recht praktisch. Oder gibts so etwas auch direkt für strings?

    MfG
    unicode frager



  • Jochen Kalmbach schrieb:

    Was sind 50 KB?

    wie sagte doch ein bekannter computerjunkie: '640K ought to be enough for anybody...'
    na, dann zähl doch mal bis 51200...



  • unicode frager schrieb:

    Jochen Kalmbach schrieb:

    Und warum willst Du stringstream? wenn Du bisher auch ohne ausgekommen bist?

    Ich hab öfters sprintf in meinem Programm, wenn ich nun mit strings arbeite muss ich die ja erst wieder umständlich zu const char* umwandlen und zurück, da ist die stringstream lib doch recht praktisch. Oder gibts so etwas auch direkt für strings?

    Ich verwenden (wenn ich mal keine MFC hab) immer CStdString.
    http://home.earthlink.net/~jmoleary/stdstring.htm
    http://www.codeproject.com/string/stdstring.asp

    Kann ähnliches wie CString (also TCHAR als Basis!) und ist Platform neutral!

    Kann ich nur empfehlen!



  • unicode frager schrieb:

    Danke mal für die Antworten.

    Ich benutze im Grunde ein Mischmasch von C und C++ in meinem Programm. Die std::string Funktionen sind schon praktisch, lassen mein Programm aber gleich mal 50kB größer werden. Und wenn ich dann auch noch die stringstream Funktionen nutzen will, sind es noch mal gut 250kB mehr! Wenn du was kleineres zur Verfügung hättest, gerne 🙂

    Im Debug oder im Release-Modus?



  • Jochen Kalmbach schrieb:

    Ich verwenden (wenn ich mal keine MFC hab) immer CStdString.
    http://home.earthlink.net/~jmoleary/stdstring.htm
    http://www.codeproject.com/string/stdstring.asp

    Kann ähnliches wie CString (also TCHAR als Basis!) und ist Platform neutral!

    Sieht interessant aus! Werde ich mir mal anschauen.

    Neku schrieb:

    unicode frager schrieb:

    Danke mal für die Antworten.

    Ich benutze im Grunde ein Mischmasch von C und C++ in meinem Programm. Die std::string Funktionen sind schon praktisch, lassen mein Programm aber gleich mal 50kB größer werden. Und wenn ich dann auch noch die stringstream Funktionen nutzen will, sind es noch mal gut 250kB mehr! Wenn du was kleineres zur Verfügung hättest, gerne 🙂

    Im Debug oder im Release-Modus?

    Das hier im Release und gestripped gibt eine 256kB EXE (MinGW)!

    #include <windows.h>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    int main(void)
    {
        stringstream    sstrTest;
        string          strIn;
        string          strTest  = "Hallo";
        int             i = 5;
    
        strIn = strTest + " Test";
    
        strIn += " Ich";
    
        MessageBox( NULL, strIn.c_str(), "Versuch", MB_OK );
    
        sstrTest << strIn << i << "Jahre alt!" << endl;
    
        strIn += sstrTest.str();
    
        MessageBox( NULL, strIn.c_str(), "Versuch 2", MB_OK );
    
        return 0;
    }
    

    Das kann ich mir nicht antun 😉

    MfG
    unicode frager



  • Hab mir mal CStdString kurz angeschaut und finde es genial. Funktioniert leider nur mit VC++ aber naja. Allerdings habe ich ein paar Warings die ich nicht verstehe und nicht weiß ob sie "gefährlich" sein könnten.

    c:\StdString.h(2120) : warning C4311: 'type cast' : pointer truncation from 'const void *' to 'unsigned long'
            c:\StdString.h(2116) : while compiling class-template member function 'bool CStdStr<CT>::TryLoad(const void *)'
            with
            [
                CT=char
            ]
            c:\StdString.h(3940) : see reference to class template instantiation 'CStdStr<CT>' being compiled
            with
            [
                CT=char
            ]
    c:\StdString.h(2122) : warning C4311: 'reinterpret_cast' : pointer truncation from 'const void *' to 'unsigned long'
    c:\StdString.h(2125) : warning C4311: 'reinterpret_cast' : pointer truncation from 'const void *' to 'unsigned long'
    c:\StdString.h(2120) : warning C4311: 'type cast' : pointer truncation from 'const void *' to 'unsigned long'
            c:\StdString.h(2116) : while compiling class-template member function 'bool CStdStr<CT>::TryLoad(const void *)'
            with
            [
                CT=wchar_t
            ]
            c:\StdString.h(3973) : see reference to class template instantiation 'CStdStr<CT>' being compiled
            with
            [
                CT=wchar_t
            ]
    c:\StdString.h(2122) : warning C4311: 'reinterpret_cast' : pointer truncation from 'const void *' to 'unsigned long'
    c:\StdString.h(2125) : warning C4311: 'reinterpret_cast' : pointer truncation from 'const void *' to 'unsigned long'
    

    Kann man das so stehen lassen?

    Zur Größe: Selbes Programm ~48kB 😃

    MfG
    unicode frager



  • Du hast vermutlich die 64-Bit Warnungen aktiviert... der CStdString ist da vermutlich noch nicht 100% korrekt... aber solange Du es bisher nur für x86 verwenden willst, kannst Du es ignorieren... oder natürlich die "Fehler" korrekt beheben...



  • Jep die sind aktiviert. Dann ist's ja nicht so schlimm.
    Muss man eigentlich einen CStdString auch wieder freeen 😉
    Also mit string.free oder sowas?

    MfG
    unicode frager



  • Das ist ja eine Klasse und wird somit durch den Destruktor automatisch wieder freigegeben...



  • Hallo ich bin's mal wieder.

    Benutze jetzt CStdString und soweit läuft auch alles recht gut. Nun wollte ich auch meine IMAGEHLP_SYMBOL und IMAGEHLP_LINE Strukturen auf Unicode umstellen und siehe da, Pech gehabt, geht nicht! Laut MSDN sollte es jeweils die wide-Strukturen geben, aber der Compiler meckert er kann sie nicht finden?

    MSDN schrieb:

    Implemented as IMAGEHLP_SYMBOLW64 (Unicode) and IMAGEHLP_SYMBOL64 (ANSI).

    Und wie läuft das mit z.B. SymGetSymFromAddr64, gibt es davon auch eine Unicodefunktion?

    Normalerweiße wenn ich eine Buffer als Parameter übergeben muss, kann ich ja string.GetBuffer() aufrufen um einen CStdString zu erhalten und mit diesen zu arbeiten, aber wie mache ich das bei den betroffenen Strukturmembern? Habs versucht, bekomme es aber nicht gebacken.

    Hoffe auf Hilfe 💡

    MfG
    unicode frager



  • Welche Version von VS? Die Unicode-Version ist erst sehr spät dazugekommen...
    Ist erst ab VS2005 dabei oder in einem sehr neuen PSDK...
    Auch musst Du dann eine dbghelp.dll haben, welche diese Unicode-Version hat.

    PS: Für die Verwendung von dbghelp.dll siehe auch mein Artikel auf CP:
    http://www.codeproject.com/threads/StackWalker.asp



  • Hab VC 7.1, dann muss ich mir nochmal überlegen, ob ich Unicode unterstütze, da ich ja dann auch wahrscheinlich die dbghelp.dll mitlifern müsste, naja.

    Dabke erstmal.

    MfG
    unicode frager


Log in to reply