Out of scope pointer - how to fix?



  • Hello,

    I have Class A and Class B.
    Class A has a member "QList<Class B *> myList;" including several Class B's.

    @ClassB *b = new ClassB(pch);
    myList.append(b);@

    "pch" is:
    @wchar_t lpBuffer[MAX_PATH] = {0};
    wchar_t *pch = lpBuffer;@

    as lpBuffer is "trashed":
    @pch = &pch[wcslen(pch) + 1];@

    "pch" is also trashed in the end. My object and pointer is freed.

    I want to send a const value to the constructor of ClassB as seen above where it is copied into ClassB's "wchar_t * pointer" *pointer object.

    How to do this? I am a beginner and don't get further... ;-)

    If I call some functions inside the constuctor, it works as expected.
    As soon as I go thru my QList, the object is garbage (sure it is, its only local and the scope is left).


  • Moderators

    You need to give more details about your code for proper answering, but it looks like you are using a temporary object for instance like in:
    @
    void foo ()
    {
    {
    wchar_t lpBuffer[MAX_PATH] = {0};
    wchar_t *pch = lpBuffer;

         // pointer should be valid in here 
      }
    

    // pointer is no longer valid
    }
    @
    You need to allocate memory with new.

    BTW it has nothing to do with Qt



  • @void TaskHdd::getLocalDisks()
    {
    DWORD nBufferLength = MAX_PATH;
    wchar_t lpBuffer[MAX_PATH] = {0};

    DWORD dwResult = GetLogicalDriveStrings(nBufferLength,lpBuffer);
    
    if (dwResult > 0 && dwResult <= MAX_PATH)
    {
        wchar_t *pch = lpBuffer;
    
        while (*pch) {
            // Type 3 = fixed drive
            if(GetDriveType(pch) == 3)
            {
                HddAllocation *hdd = new HddAllocation(pch);
                hardDiskAllocationList.append(hdd);
            }
    
            // jump to next drive
            pch = &pch[wcslen(pch) + 1];
        }
    
    }else{
        //TODO: Log - no local HDDs found.
    }
    

    }@

    "HddAllocation(pch);": In my constructor I copy the pointer to pointer, I know this can't work as soon as the constructor is left (return).

    @HddAllocation::HddAllocation(const wchar_t *mountPoint, QObject *parent ) :
    QObject(parent)
    {
    lpDirectoryName = mountPoint;
    lpFreeBytesAvailable = new ULARGE_INTEGER;
    lpTotalNumberOfBytes = new ULARGE_INTEGER;
    lpTotalNumberOfFreeBytes = new ULARGE_INTEGER;

    //get initial values
    refreshValues();
    

    }@

    I want to change my code - my constrcutor should get a static wchar_t which is written into my "wchar_t *hddName;".

    As the object behind lpBuffer is just temp, the current behavior is "working as expected". I just don't know how to copy the const inside my constrcutor.



  • What do you mean by "I just don’t know how to copy the const inside my constrcutor"?

    Do you mean to say you want to copy the data pointed to by const wchar_t *mountPoint? (i.e. you want to store that "string"?)

    Or you just want to copy the pointer value itself?


  • Moderators

    This will do it:
    @
    auto len = wcslen(mountPoint);
    lpDirectoryName = new wchar_t[len+1];
    lpDirectoryName[len] = 0;
    memcpy(lpDirectoryName, mountPoint, len * sizeof(wchar_t));
    @

    But seriously I would suggest you use QString and don't fiddle with "new" and raw pointers so much.



  • [quote author="Chris Kawa" date="1393861342"]
    @
    auto len = wcslen(mountPoint);
    lpDirectoryName = new wchar_t[len+1];
    lpDirectoryName[len] = 0;
    memcpy(lpDirectoryName, mountPoint, len * sizeof(wchar_t));
    @
    [/quote]

    Perfect! This is what I searched for the whole day ;-)

    You are true, I would like to avoid MS VC++ and Qt mix but Win32API (which I am implementing in my app) needs pointer wchar_t's. I would like to use Qt classed instead.

    Thanks for your help, I did not know that I need to specify the array length, I just allocated via "new wchar_t" and memcpy'ed the content (this also explains why this was not working, as it was the wrong length).


  • Moderators

    Yeah, it works, but I would still recommend something like:
    @
    QStringList logicalDrives()
    {
    auto length = GetLogicalDriveStrings(0, nullptr);
    auto array = std::make_unique<wchar_t[]>(length + 1);
    GetLogicalDriveStrings(length + 1, array.get());
    return QString::fromWCharArray(array.get(), length)
    .split(QChar('\0'), QString::SkipEmptyParts);
    }
    @

    No "new"s, don't have to worry about freeing stuff, no memcpy (yuck) etc.



  • And how do I cast QString to wchar_t?

    @BOOL WINAPI GetDiskFreeSpaceEx(
    In_opt LPCTSTR lpDirectoryName,
    Out_opt PULARGE_INTEGER lpFreeBytesAvailable,
    Out_opt PULARGE_INTEGER lpTotalNumberOfBytes,
    Out_opt PULARGE_INTEGER lpTotalNumberOfFreeBytes
    );@


  • Moderators

    Eg.
    @
    QString s = "whatever";
    WhateverWinAPICall(s.toStdWString().c_str());
    @



  • Thanks, I will try this.
    Slowly I get into this.


  • Moderators

    You like to copy lpBuffer (the pointer) or the content it points to?

    At the moment you are copying the pointer only and keep.
    This like making a scratch in the paint of a boat where someone was falling off. In harbor you can tell the rescue guys exactly where the guy felt off. Unfortunately, it will not rescue the guy from drowning ;- )

    In the constructor you would need to allocate memory and copy from one pointer to the other.

    @
    lpDirectoryName = new wchar_t [MAX_PATH];
    memcpy (lpDirectoryName, mountPoint, sizeof (wchar_t) * MAX_PATH);
    @
    Please check with size. This is not tested.

    Alternatively, you can copy byte by byte in a for loop.

    Personally I would copy the information to string. std::string or QString. The followup handling is easier.

    [edit, since interrupted, I had missed out the other exchange, koahnig]



  • [quote author="Chris Kawa" date="1393862155"]Yeah, it works, but I would still recommend something like:
    @
    QStringList logicalDrives()
    {
    auto length = GetLogicalDriveStrings(0, nullptr);
    auto array = std::make_unique<wchar_t[]>(length + 1);
    GetLogicalDriveStrings(length + 1, array.get());
    return QString::fromWCharArray(array.get(), length)
    .split(QChar('\0'), QString::SkipEmptyParts);
    }
    @

    No "new"s, don't have to worry about freeing stuff, no memcpy (yuck) etc.[/quote]

    How can I do the same without C++11? Auto and nullptr are undefined and even std::make_unique throws "is not a member" when C++11 is enabled.

    Thanks.


  • Moderators

    Yeah, sorry, make_unique is actually part of C++14 but newer compilers already support it for some time so I'm used to it (I can't recommend enough to upgrade. It's another world :) ).

    In C++03 just replace the nice stuff with the ugly one :)
    @
    QStringList logicalDrives()
    {
    DWORD length = GetLogicalDriveStrings(0, NULL);
    QScopedPointer<wchar_t, QScopedPointerArrayDeleter<wchar_t> > array(new wchar_t[length+1]);
    GetLogicalDriveStrings(length + 1, array.data());
    return QString::fromWCharArray(array.data(), length)
    .split(QChar('\0'), QString::SkipEmptyParts);
    }
    @



  • Do I have any new dependencies for my application? I am using Qt 5.2.1, most likly I upgrade to any new release. If there are no new dependencies, I would upgrade, too.


  • Moderators

    Well it depends on what you're using now :)
    For MSVC make_unique is available from VS2013 (or VS2012 November CTP to be precise) and if you're using MinGW 4.8 from the online installer it's already there, you just need to add QMAKE_CXXFLAGS += -std=c++1y in the .pro file.

    As for app dependencies - only the usual: Qt libs, plugins, and system/compiler runtime just like in any version.



  • -I still get this warning:-
    @C:\folder\file.cpp:53: Warnung: 'auto' changes meaning in C++11; please remove it [-Wc++0x-compat]@

    -as well as:-
    @C:\folder\file.cpp:53: Fehler: 'length' does not name a type
    auto length = GetLogicalDriveStrings(0, nullptr);
    ^@

    -I tried the online MinGW install, but there are components missing / headers are not compatible anymore in several of my classes.-

    Works now, just had to comment out my WINVER define.
    Now I am not able to compile some spcial Vista+ APIs but I can solve this later.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.