0

I'm using following code:

int main () {
    wchar_t *serial = new wchar_t[1];
    wchar_t *user = new wchar_t[1];
    size_t strLen;

    do {
        wprintf (L"Username (between 4 and 30 characters): ");
        wscanf (L"%ls", user);
    } while ((strLen = wcslen (user)) < 4 || strLen > 30);

    wprintf (L"Serial key: ");
    wscanf (L"%ls", serial);

    std::getchar ();
    std::getchar (); // Twice, because of trailing \n of wscanf()

    delete[] serial; // Error!
    delete[] user;

    return 0;
}

Everytime I'm getting an assertion failure. Here I read that I have to use delete[] instead of delete, if I want to deallocate arrays. So I corrected my code and was still getting the exact same error. In this forum I read that the pointer that I want to delete mustn't change. I checked my pointer with cout << (int)serial; and the printed number wasn't changing. How to deallocate an array? Everytime I use delete (no matter when/where) I get assertion failures. Am I making something wrong?

Community
  • 1
  • 1
Cubi73
  • 1,891
  • 3
  • 31
  • 52
  • 3
    A null-terminated serial key and username between 4 and 30 characters most certainly do not fit in one character. Use `std::wstring`, not `wchar_t *`. – chris Aug 06 '14 at 23:22

1 Answers1

4

There is nothing wrong with the way you are deallocating the memory, the problem is with the way you are allocating and using it:

wchar_t *serial = new wchar_t[1];
wchar_t *user = new wchar_t[1];

You have allocated just one char for each variable. The number between [] is how many elements to allocate, in this case how many wchar_ts.

What happens is that there is nothing stopping the user from writing a lot more chars into user[]/serial[] on the calls to:

wscanf (L"%ls", user); 
wscanf (L"%ls", serial);

wscanf doesn't do bounds checking on the array. If the user writes more than 1 char in the terminal, wscanf will be writing outside the bounds of the arrays, corrupting the memory space of your program and triggering an assertion when that memory is later deallocated and consequently validated by delete[].

Suggested fix:

#include <cstdio>
#include <iostream>
#include <string>

int main()
{
    std::wstring serial;
    std::wstring user;
    size_t strLen = 0;

    do {

        std::wcout << L"Username (between 4 and 30 characters): ";
        std::wcin >> user;

    } while ((strLen = user.length()) < 4 || strLen > 30);

    std::wcout << L"Serial key: ";
    std::wcin >> serial;

    std::getchar();

    std::wcout << L"User....: " << user   << std::endl;
    std::wcout << L"Serial..: " << serial << std::endl;

    return 0;
}

Avoid using raw pointers if possible by using std::string and std::wstring. Also, prefer std::cout and std::wcout for terminal/console IO.

glampert
  • 4,371
  • 2
  • 23
  • 49
  • 2
    A pointer to use `std::wstring` instead of `wchar_t*` would be nice. – πάντα ῥεῖ Aug 06 '14 at 23:39
  • I forgot that I was using 1 element. This was a test from before my current project. I wanted to find out when the assertion failure occurs, because it seemed to occur randomly. With 1 element it was more everytime than randomly. Thank you anyways :) – Cubi73 Aug 06 '14 at 23:43
  • @πάνταῥεῖ, added suggested implementation using `std::wstring` instead. – glampert Aug 06 '14 at 23:49
  • @Cubinator73, make sure to take a look at my suggested fix and possibly switch to strings. They are always preferred over raw pointers when in C++. – glampert Aug 06 '14 at 23:51
  • @glampert I'm definitely going to do this :) – Cubi73 Aug 07 '14 at 00:54