2017-04-04 1 views
0

sudo dd if=/dev/sda ibs=1 count=64 skip=446 명령을 사용하여 구문 분석을 위해 마스터 부트 레코드에서 파티션 테이블 정보를 얻으려고합니다. 기본적으로 구문 분석을 위해 문자열로 출력하지만 모두 다음과 같습니다. � !. 내가 기대하고있어입니다 :C++ 프로그램에서 Linux 'dd'명령의 출력을 얻는 데 문제가 있음

80 01 01 00 83 FE 3F 01 3F 00 00 00 43 7D 00 00 00 00 01 02 83 FE 3F 0D 82 7D 00 00 0C F1 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

내 현재 코드는 다음과 같습니다, 그리고 여기에서 가져온 것입니다 : How to execute a command and get output of command within C++ using POSIX?

#include <iostream> 
#include <stdexcept> 
#include <stdio.h> 
#include <string> 

using namespace std; 

string exec(const char* cmd) { 
    char buffer[128]; 
    string result = ""; 
    FILE* pipe = popen(cmd, "r"); 
    if (!pipe) throw std::runtime_error("popen() failed!"); 
    try { 
     while (!feof(pipe)) { 
      if (fgets(buffer, 128, pipe) != NULL) 
       result += buffer; 
     } 
    } catch (...) { 
     pclose(pipe); 
     throw; 
    } 
    pclose(pipe); 
    return result; 
} 

int main() { 

    string s = exec("sudo dd if=/dev/sda ibs=1 count=64 skip=446"); 
    cout << s; 

} 
내가 뭔가를 잘못하고 있어요 분명히

하지만 내가 할 수있는 ' 문제를 찾아 내십시오. 내 문자열에 적절한 출력을 얻으려면 어떻게해야합니까?

+0

그런데 왜 [while (! feof (file))가 항상 잘못 되었습니까?] (http://stackoverflow.com/questions/5431941/why-is-while-feof-file)를 읽어야합니다. -always-wrong) – molbdnilo

+1

명령 줄에서 명령을 실행하면 출력이 예상 한 것입니까? 명령은 원시 이진 데이터를 덤프하기 때문에 심각하게 의심 스럽습니다. 원시 이진 데이터는 텍스트처럼 처리 될 수 없습니다. –

+0

또한 왜 독서 루프를'try-catch'에 넣고 있습니까? 예외를 일으킬 수있는 유일한 것은 문자열에 추가하는 동안 메모리가 부족한 경우입니다. 그렇더라도 프로그램 종료로 인해 파이프가 닫히기 때문에 실용적인 필요는 없습니다. –

답변

0
while (!feof(pipe)) { 

이것은 your first bug입니다.

result += buffer; 

이것은 두 번째 버그입니다. bufferchar 어레이이며,이 컨텍스트에서 char *으로 붕괴됩니다. 알다시피, 문자열 컨텍스트의 char *은 일반적으로 '\0'바이트로 끝나는 C 스타일 문자열로 해석됩니다.

00 바이트를 읽는 것으로 나타났습니다. 글쎄, char 어레이가 char *으로 감 소한 후에는 첫 번째 00 바이트까지의 모든 것이 정확하게 128 바이트가 아니라 result에 추가됩니다. 그리고 그 128 바이트에 00 바이트가 없다면, 당신은 아마 충돌의 작은 가능성과 함께 여분의 보너스로서, 임의의 쓰레기를 버리게 될 것입니다.

if (fgets(buffer, 128, pipe) != NULL) 

이것은 세 번째 버그입니다. 읽은 데이터에 0A 바이트, 즉 '\n' 문자가 포함 된 경우 128 바이트를 읽지 않습니다.

cout << s; 

이것은 네 번째 버그입니다. 데이터는 (다른 모든 버그가 수정 된 후에) 아마도 바이너리를 포함하기 때문에, 터미널은 다양한 바이트, 특히 바이트 00에서 1F까지를 성공적으로 보여줄 것 같습니다.

  1. 올바르게 파일 끝 조건을 처리 :

    는 당신이 필요합니다 코드를 수정합니다.

  2. 이진 데이터를 올바르게 읽습니다. fgets(), 등은 작업에 완전히 부적합합니다. C 파일 구조 사용을 주장하는 경우 fread()을 사용하는 것이 합당한 옵션입니다.

  3. 이진 데이터 블로브에서 std::string을 올바르게 조립하십시오. char 버퍼를 추가하고 손가락을 엇갈리게 가며 최상을 기대하면서 작동하지 않습니다. 두 인자 인 std::string 생성자를 사용해야 할 것입니다. 생성자는 시작과 끝 반복자 값을 매개 변수로 사용합니다.

  4. 그냥 BLOB 전체를 std::cout으로 덤프하는 대신 올바르게 이진 데이터를 표시합니다. 가장 일반적인 방법은 std::hex 조작자이며 각 charint, 으로 부지런히 변환하여 부호 없음 값으로 만듭니다.

관련 문제