[C][筆記] Win8 下 clrscr 函數 0xC0000005 存取違規

今天寫作業遇到的一個問題,害我只能用學校的 XP 寫  (怨念
clrscr 是 conio 裡的一個函數,不過大部分的 header 裡好像都沒有他  (DevC 表示
所以有附上另外的 function 給我們調用,但想不到在 Win8 下居然無法開啟範例程式,就算自己編譯也會錯誤...
本人 Win8 x64,這個程式碼在網路上隨處可見,XP、Win7 測試都沒有問題,回來給他 debug 看問題到底在哪(懶得重寫函數)畢竟聽說之後還會常常用到  (笑

先附上網路上隨處可見的版本
void clrscr(void)
{
    CONSOLE_SCREEN_BUFFER_INFO sbinf;
    int size;
    COORD scrn = {0, 0};
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    GetConsoleScreenBufferInfo(hStdOut, &sbinf);
    size = (sbinf.srWindow.Right-sbinf.srWindow.Left+1)*
        (sbinf.srWindow.Bottom-sbinf.srWindow.Top+1);
    FillConsoleOutputCharacter(hStdOut, 32, size, scrn, NULL);
}
Dev 表示:_____(已當
VC 表示:0x76ACED95 (KernelBase.dll) (於 ConsoleApplication2.exe) 中第一個可能發生的例外狀況: 0xC0000005: 寫入位置 0x00000000 時發生存取違規。

去記憶體中看了一下 0x76ACED95 在搞甚麼鬼,KERNELBASE 表示這是 WriteConsoleOutputAttribute 這個 API,然後我們看一下上面那個函數,就知道問題出在 FillConsoleOutputCharacter 這了!  (至於怎麼看... 對 API 有一定了解應該看的出來

看一下 MSDN 的介紹...
BOOL WINAPI FillConsoleOutputCharacter(
  _In_   HANDLE hConsoleOutput,
  _In_   TCHAR cCharacter,
  _In_   DWORD nLength,
  _In_   COORD dwWriteCoord,
  _Out_  LPDWORD lpNumberOfCharsWritten
);
根據錯誤訊息,寫入了 0x00000000 這個位置,也就是寫入了一個空指標造成記憶體存取違規程式當掉,雖然不知道為什麼到 Win8 這邊就不能用 NULL 了,只能猜是 Kernel 有改某些使用上變嚴格了吧?
(有興趣去比較 Kernel 差異的歡迎留言...

講這麼久那到底要怎麼改才能用呢?
只要把原本回傳 LPDWORD lpNumberOfCharsWritten 不要傳到空指標改宣告一個 DWORD 當暫存即可...
void clrscr(void)
{
    CONSOLE_SCREEN_BUFFER_INFO sbinf;
    int size;
    COORD scrn = {0, 0};
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD temp;
    GetConsoleScreenBufferInfo(hStdOut, &sbinf);
    size = (sbinf.srWindow.Right-sbinf.srWindow.Left+1)*
        (sbinf.srWindow.Bottom-sbinf.srWindow.Top+1);
    FillConsoleOutputCharacter(hStdOut, 32, size, scrn, &temp);
}
至少我以後可以繼續用我的 Win8 來寫了哼哼啊阿 :P

本月最夯