behnam
behnam

Reputation: 179

C++, win32 error

I'm trying to run the code below:

#include "stdafx.h"
#include <windows.h>
#include <winspool.h>
HDC GetPrinterDC (void)
{
    DWORD dwNeeded, dwReturned ;
    HDC hdc ;
    PRINTER_INFO_4 * pinfo4 ;


        EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, NULL,
            0, &dwNeeded, &dwReturned) ;
        pinfo4 = new PRINTER_INFO_4 [dwNeeded/sizeof(PRINTER_INFO_4)] ;
        EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE) pinfo4,
            dwNeeded, &dwNeeded, &dwReturned) ;
        hdc = CreateDC (NULL, pinfo4->pPrinterName, NULL, NULL) ;
        free (pinfo4) ;

    return hdc ;
}

but I keep getting the error "Win32Project1.exe has triggered a breakpoint.". When I press continue I endup with the error "Debug assertion failed". The error is happening on the "free(pinfo4)" line.

Any help would be most appreciated.

Additional Notes: also tried "delete [] pinfo4;"

Additional Notes: The program displays this when it breaks. It is not my code: https://drive.google.com/file/d/0BwFUfWkiqC7VZkdrU04zZ3pqZUU/view?usp=sharing

Upvotes: 0

Views: 207

Answers (4)

Victor Zhuravlev
Victor Zhuravlev

Reputation: 11

You probably allocating less space than needed. Consider (theoretical) situation where dwNeeded = 5 and sizeof(PRINTER_INFO_4) = 4.

Your code will allocate single ( 5 / 4 == 1 ) PRINTER_INFO_4 and EnumPrinters will overrun supplied buffer. It is better to allocate exactly dwNeeded BYTEs and than reinterpret_cast them to PRINTER_INFO_4.

And, as marcinj said, you should use either malloc/free or new[]/delete[].

Upvotes: 0

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145194

From the docs, emphasis added:

the buffer must be large enough to receive the array of data structures and any strings or other data to which the structure members point. If the buffer is too small, the pcbNeeded parameter returns the required buffer size.

This means that buffer is not all array. Hence computing the number of array items and allocating only that can give you a too short buffer. Consider either just allocating bytes, or rounding up instead of down the division result.


Also, don't allocate with new and deallocate with free. That's formal UB. Instead, just use a std::vector of bytes.

Upvotes: 1

Elixir Techne
Elixir Techne

Reputation: 1856

Can you try below code

#include "stdafx.h"
#include <windows.h>
#include <winspool.h>
HDC GetPrinterDC (void)
{
    DWORD dwNeeded, dwReturned ;
    HDC hdc ;
    PRINTER_INFO_4 * pinfo4 ;


        EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, NULL,
            0, &dwNeeded, &dwReturned) ;
        if (dwNeeded <= 0)
            return NULL;
        pinfo4 = new PRINTER_INFO_4 [dwNeeded/sizeof(PRINTER_INFO_4)] ;
        EnumPrinters (PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE) pinfo4,
            dwNeeded, &dwNeeded, &dwReturned) ;

        hdc = CreateDC (NULL, pinfo4[0]->pPrinterName, NULL, NULL) ;
        delete [] pinfo4 ;

    return hdc ;
}

Upvotes: 0

marcinj
marcinj

Reputation: 49976

Insted of free (pinfo4) ; you should use delete[] pinfo4. Use free together with malloc - and thats for C programs. In c++ use new and delete.

Another strange thing about your code, you use: pinfo4->pPrinterName,, but pinfo4 is an array, so you should use rather: pinfo4[0]->pPrinterName, or some other index. Also make sure dwNeeded is non zero.

Upvotes: 2

Related Questions