Search code examples
c++memory-leaksnew-operatordelete-operator

Should we use delete[] or delete on function that return allocated memory pointer?


Should i use delete[] or delete for Register() example below? We hit some memory leak issue and legacy code which is not allow to change the return type and input of the function. I understand that new[] should use delete[]. new should use delete. However for case below, which method is correct?

UINT Register(UINT regaddr, usb_dev_handle* current_handle)
{
    unsigned int val= 0;
    unsigned char* buffer = readregister(current_handle, char((regaddr >> 8) & 0x00FF), char(regaddr & 0x00FF));
    raddrvaluefinal = buffer[2] << 8 | buffer[3];

    delete buffer;
    return val;
}

unsigned char* readregister(usb_dev_handle *current_handle, char one, char two)
{
    unsigned char *buffer = new unsigned char[4];
    char cmd[2];
    cmd[0] = 'D';
    cmd[1] = 'B';
    int rv = 0;
    unsigned char bin_size[2];
    buffer[0] = one + 0x80;
    buffer[1] = two;
    buffer[2] = buffer[3] = 0;
    usb_bulk_write(current_handle, 0x02, cmd, 2, 500);
    bin_size[0] = (5 / 4) & 0x0FF;
    bin_size[1] = ((5 / 4) >> 8) & 0x0FF;
    rv = usb_bulk_write(current_handle, 0x01, (char*)bin_size, 2, 2000);
    unsigned int byteswrite += usb_bulk_write(current_handle, 0x04, (char*)buffer, 4, 2000);
    unsigned int bytesread += usb_bulk_read(current_handle, 0x86, (char*)buffer, 4, 2000);
    buffer[0] = one;
    buffer[1] = two;
    return buffer;
}

Solution

  • I understand that new[] should use delete[]. new should use delete.

    unsigned char *buffer = new unsigned char[4];
    ...
    delete buffer;
    

    The program is wrong, and against your understanding. When a dynamic array is allocated dynamically with new[], delete[] must be used to deallocate it. If you use delete, then the behaviour of the program is undefined.


    You shouldn't use owning bare pointers in the first place, and in this case there doesn't even seem to be any need to use a dynamic array. I recommend following instead:

    std::array<unsigned char, 4>
    readregister(usb_dev_handle *current_handle, char one, char two)
    {
        std::array<unsigned char, 4> buffer;
        // ...
        usb_bulk_write(current_handle, 0x04, reinterpret_cast<char*>(buffer.data()), 4, 2000);
    

    Sidenote: "new -> delete", "new[] -> delete[]" is a slight oversimplification. delete[] must be used if new is used to create an array:

    using T = int[4];
    int* ptr = new T;
    delete[] ptr; // correct