2017-03-09 1 views
-3

C (C++이 아님)와 함께 cmd 프롬프트를 씁니다. 프로그램이 컴파일되지만 실행될 때 여러 번 명령을 입력하면 프로그램 버그와 중단이 발생합니다. 생각합니다. 메모리 할당에 : 는 SO이는 소스 코드 : 처음에, n_buffersize = 0, 그래서 당신은 단지 1 바이트를 할당하는C (할당)의 메모리 관리

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

참고 : 당신이

#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

. 그런 다음 sizeof(char*) 바이트 수 (32 비트 시스템에서는 4 바이트, 64 비트 시스템에서는 8 바이트)를 제로화합니다.

할당 한 바이트 수를 0으로 설정할 수 있습니다. 즉, n_buffersize + 1입니다. 또는 malloc() 대신 calloc()을 사용하십시오.

0

Execute()의 메모리 관리를 간소화 할 수 있습니다. 특히 strcat()에서 두 개의 버퍼를 사용하는 것은 비효율적입니다. 더 중요한 것은 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; 
}