2017-03-09 18 views
-3

私はC(C++ではない)を使ってcmdプロンプトを書きます。プログラムはコンパイルされますが、実行すると何回かコマンドを入力するとプログラムのバグが発生し、中止します メモリ割り当てに:あなたが持っているC(割り当て)のメモリ管理

#include <stdio.h> 
#include <stdlib.h> 
#include <Windows.h> 

char* Execute(char*); 

HANDLE readIN = NULL; 
HANDLE writeIN = NULL; 
HANDLE readOUT = NULL; 
HANDLE writeOUT = NULL; 



int 
main(int argc, char** argv) 
{ 
    SECURITY_ATTRIBUTES saAttr; 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    char cmd[12]; 
    char* out = NULL; 
    ZeroMemory(cmd,sizeof(cmd)); 


    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 

    CreatePipe(&readOUT, &writeOUT, &saAttr, 0); 
    CreatePipe(&readIN, &writeIN, &saAttr, 0); 

    ZeroMemory(&si, sizeof(si)); 
    ZeroMemory(&pi, sizeof(pi)); 
    GetStartupInfo(&si); 

    si.cb = sizeof(STARTUPINFO); 
    si.hStdError = writeOUT; 
    si.hStdOutput = writeOUT; 
    si.hStdInput = readIN; 
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 
    si.wShowWindow = SW_HIDE; 

    CreateProcess(NULL, 
       "cmd.exe", 
        NULL, 
        NULL, 
        TRUE, 
        CREATE_NEW_CONSOLE, 
        NULL, 
        NULL, 
        &si, 
        &pi 
       ); 

    while (TRUE) 
    { 
     out = Execute(cmd); 
     printf("%s\n", out); 
     scanf("%s", cmd); 
     strcat(cmd,"\n"); 
    } 
    free(out); 
    return 0; 
} 


char* 
Execute(char* cmd) 
{ 
    DWORD bwritten = 0; 
    DWORD buffersize = 0; 
    int outputsize = 0; 
    DWORD breaden = 0; 
    char* output = NULL; 
    char* buffer = NULL; 
    DWORD n_buffersize; 
    WriteFile(writeIN, cmd, strlen(cmd), &bwritten, NULL); 
    while (TRUE) 
    { 
     Sleep(2000); 
     PeekNamedPipe(readOUT, NULL, NULL, NULL,&buffersize, NULL); 
     n_buffersize = buffersize; 
     if (n_buffersize) 
     { 
      buffer = (char*)malloc(n_buffersize + 1); 
      ZeroMemory(buffer,sizeof(buffer)); 
      ReadFile(readOUT, buffer, n_buffersize, &breaden, NULL); 
     } 
     else 
      break; 

     if (breaden) 
     { 
      outputsize += n_buffersize + 1; 
      output = (char*)realloc(output, outputsize); 
      strcat(output, buffer); 
      free(buffer); 
     } 
    } 
    return output; 
} 
+3

と*中止は全く役に立たない問題の説明です。 **あなたが投稿したコードで**あなたは特定の**問題がありますか?デバッガは、コードをステップ実行したときに何を伝えますか? –

+0

デバッガmsg:mycmd.exeの0x77BF62AC(ntdll.dll)に対する未処理例外:0xC0000374:メモリセグメントが破損しています(パラメータ:0x77C26480)。起こった –

答えて

4

:最初に、n_buffersize = 0ので、あなただけの1バイトを割り当てている

buffer = (char*)malloc(n_buffersize + 1); 
ZeroMemory(buffer,sizeof(buffer)); 

注 SOこれは、ソースコードです。 しかし、sizeof(char*)バイト数(32ビットシステムでは4バイト、64ビットシステムでは8バイト)をゼロにします。

割り当てたバイト数をゼロにすることができます。これはn_buffersize + 1です。またはmalloc()の代わりにcalloc()を使用してください。

0

Execute()のメモリ管理を合理化することができます。特にstrcat()で2つのバッファを使用することは非効率的です。しかし、もっと重要なのは、main()のループが、割り当て方法にかかわらず、Execute()が出力するメモリをリークしていることです。

あなたはまた、MSDNに記載されていSTD(IN|OUT|ERR)リダイレクトに関するガイドライン以下のすべてがされていません。つまり、あなたが継承すべきではない、とあなたはそのハンドルを閉じていないハンドルを継承している

Creating a Child Process with Redirected Input and Output

cmd.exeが実行されている間は使用していません。

代わりに、より多くのこのような何かを試してみてください:プログラムのバグ*

#include <stdio.h> 
#include <stdlib.h> 
#include <Windows.h> 

char* Execute(char*); 

HANDLE readIN = NULL; 
HANDLE writeIN = NULL; 
HANDLE readOUT = NULL; 
HANDLE writeOUT = NULL; 

int 
main(int argc, char** argv) 
{ 
    SECURITY_ATTRIBUTES saAttr; 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    char cmd[256]; 
    char* out = NULL; 
    ZeroMemory(cmd, sizeof(cmd)); 

    ZeroMemory(&saAttr, sizeof(saAttr)); 
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 

    if (!CreatePipe(&readOUT, &writeOUT, &saAttr, 0)) { 
     // error handling... 
    } 
    if (!SetHandleInformation(readOUT, HANDLE_FLAG_INHERIT, 0)) { 
     // error handling... 
    } 

    if (!CreatePipe(&readIN, &writeIN, &saAttr, 0)) { 
     // error handling... 
    } 
    if (!SetHandleInformation(writeIN, HANDLE_FLAG_INHERIT, 0)) { 
     // error handling... 
    } 

    ZeroMemory(&si, sizeof(si)); 
    ZeroMemory(&pi, sizeof(pi)); 

    si.cb = sizeof(STARTUPINFO); 
    si.hStdError = writeOUT; 
    si.hStdOutput = writeOUT; 
    si.hStdInput = readIN; 
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 
    si.wShowWindow = SW_HIDE; 

    if (!CreateProcess(NULL, 
       "cmd.exe", 
        NULL, 
        NULL, 
        TRUE, 
        CREATE_NEW_CONSOLE, 
        NULL, 
        NULL, 
        &si, 
        &pi 
       )) 
    { 
     // error handling... 

     CloseHandle(readIN); 
     CloseHandle(writeIN); 
     CloseHandle(readOUT); 
     CloseHandle(writeOUT); 
    } 
    else 
    { 
     CloseHandle(pi.hThread); 
     CloseHandle(pi.hProcess); 

     CloseHandle(readOUT); 
     CloseHandle(writeIN); 

     do 
     { 
      if (scanf("%254s", cmd) != 1) 
       break;  
      strcat(cmd,"\n"); 

      out = Execute(cmd); 
      if (!out) { 
       printf("ERROR!\n"); 
       break; 
      } 

      printf("%s\n", out); 
      free(out); 
     } 
     while (TRUE); 

     CloseHandle(writeOUT); 
     CloseHandle(readIN); 
    } 

    return 0; 
}  

char* 
Execute(char* cmd) 
{ 
    DWORD bwritten = 0; 
    DWORD buffersize = 0; 
    int outputsize = 0; 
    DWORD bread = 0; 
    char* buffer = NULL; 
    char* output = NULL; 

    buffersize = strlen(cmd); 
    while (buffersize > 0) 
    { 
     if (!WriteFile(writeIN, cmd, buffersize, &bwritten, NULL)) 
      return NULL; 
     cmd += bwritten; 
     buffersize -= bwritten; 
    } 

    do 
    { 
     Sleep(2000); 
     if (!PeekNamedPipe(readOUT, NULL, NULL, NULL, &buffersize, NULL)) 
      break; 

     if (buffersize == 0) 
      break; 

     buffer = (char*) realloc(output, outputsize + buffersize + 1); 
     if (!buffer) { 
      free(output); 
      return NULL; 
     } 

     output = buffer; 

     if (!ReadFile(readOUT, output + outputsize, buffersize, &bread, NULL)) 
      bread = 0; 

     outputsize += bread; 
     output[outputsize] = '\0'; 
    } 
    while (bread > 0); 

    return output; 
} 
関連する問題