0

compiler : http://sourceforge.net/projects/mingwbuilds/files/

#include <iostream>
#include <string.h>
#include <windows.h>
using namespace std;

  const wchar_t* readConsole(int chars_to_read) {
    wchar_t* wcharFromConsole = new wchar_t[chars_to_read+1];
    COORD pos = {0,0};
    DWORD dwChars;
    if (!ReadConsoleOutputCharacterW(
      GetStdHandle(STD_OUTPUT_HANDLE),
      wcharFromConsole,  // Buffer where store symbols
      chars_to_read,     // number of chars to read
      pos,    // Read from row=8, column=6
      &dwChars // How many symbols stored
    ))
    {
      printf("ReadConsoleOutputCharacterW failed %d\n", GetLastError());
      abort();
    }
    wcharFromConsole [dwChars] = L'\0'; // Terminate, so string functions can be used
    wstring ws = wcharFromConsole;
    return ws.c_str();
  }

int main() {
  for (int i = 1; i<=0x3000; i++) {
    printf("wcslen: %X \n",wcslen(readConsole(i)));
  }
  system("pause");
}

This loop ends at 0x1FF1 and pause is not called. Removing wstring seems to do away with this problem. But I need it here for functions like trimming white-space etc.. it is not much relevant here, but why invoking wstring causes that issue anyway ? There is no error message the program simply quits.

Updated code, now loop quits at 0x2BBF

#include <iostream>
#include <string.h>
#include <windows.h>
using namespace std;

  const wchar_t* readConsole(int chars_to_read) {
    wchar_t* wcharFromConsole = new wchar_t[chars_to_read+1];
    COORD pos = {0,0};
    DWORD dwChars;
    if (!ReadConsoleOutputCharacterW(
      GetStdHandle(STD_OUTPUT_HANDLE),
      wcharFromConsole,  // Buffer where store symbols
      chars_to_read,     // number of chars to read
      pos,    // Read from row=8, column=6
      &dwChars // How many symbols stored
    ))
    {
      printf("ReadConsoleOutputCharacterW failed %d\n", GetLastError());
      abort();
    }
    wcharFromConsole [dwChars] = L'\0'; // Terminate, so string functions can be used
    wstring ws = wcharFromConsole;
    delete [] wcharFromConsole;
    const wchar_t* wc = ws.c_str();
    return wc;
  }

int main() {
  for (int i = 1; i<=0x3000; i++) {
    printf("wcslen: %X \n",wcslen(readConsole(i)));
  }
  system("pause");
}
rsk82
  • 28,217
  • 50
  • 150
  • 240

1 Answers1

2

Ouch.

wstring ws = wcharFromConsole;
return ws.c_str();

Basically, you are returning a dead pointer here. The string will be destroyed on the return, so the pointer arriving at the caller will be invalid.

EDIT: you're also leaking memory, since the "new" is never deleted. But that doesn't generally cause visible problems, just increasing memory use of the program.

Christian Stieber
  • 9,954
  • 24
  • 23
  • when I add `delete [] wcharFromConsole;` before `return` the loop runs longer, ends at 0x2BBF, also with no error. And I don't understand what you mean as 'dead pointer', I've updated the code in my question. – rsk82 Jul 23 '12 at 06:53
  • The pointer returned by `ws.c_str()` is only valid as long as `ws` in neither changed nor destroyed. Since `ws` is a local variable it will be destroyed when returning from the functions thus rendering the pointer returned by `ws.c_str()` invalid. – RedX Jul 23 '12 at 07:03
  • Yes, but I updated the code, now first const wchar is created, then value assigned, and then returned. I used also this way of direct returning of char[] from string without any issue until now. – rsk82 Jul 23 '12 at 07:22
  • And another thing is why it works 0x2BBF times and 0x2BC0 don't ? And why no error message is not shown ? only errorlevel is not 0 , -1073741819. – rsk82 Jul 23 '12 at 07:28