2014-06-06 2 views
1

문제를 일으키는 데 정말로 문제가 있습니다. 나는 uint32_t *에 전체 바이너리 파일을 읽고 저장하고있다. 그런 다음 필요한 데이터 세그먼트의 시작을 확인하십시오. 그러나 세그먼트의 시작 부분에 배열 변경 사항을 전달하지 않았는지 확인하기위한 수표를 추가하면 이유를 알 수 없습니다.일치하지 않는 이진 데이터 또는 조건 문 데이터 변경

#include <iostream> 
#include <string.h> 
#include <typeinfo> 
#include <fstream> 
#include <vector> 
#include <stdint.h> 
#include <stdexcept> 
using namespace std; 

int* binmem = new int[32]; 
streampos size; // size of memblock 
int blocklength; // length memblock 
uint32_t * memblock; // all data 
int startpos; 
int endpos; 
int x; 

void NewParticle() { 
    startpos = 0; 
    while (memblock[startpos]!= 0xff000000) { // 4278190080 
     if (startpos > blocklength) { 
      //cout << "nah"; 
      //x++; 
      throw invalid_argument("No start of particle"); 
     } 
     startpos++; 
    } 
} 
int main(int argc, const char *argv[]) { 
    ifstream file(argv[0], ios::in | ios::binary | ios::ate); 
    if (file.is_open()) { 
     size = file.tellg(); 
     blocklength = (size/4) + (size % 4 == 0 ? 0 : 1); 
     memblock = new uint32_t[size/4 + (size % 4 == 0 ? 0 : 1)]; 
     file.seekg(0, ios::beg); 
     file.read(reinterpret_cast<char*>(memblock), size); 
     file.close(); 
     NewParticle(); 
    } else 
     cout << "Unable to open file"; 
    return 0; 
} 

startpos는 NewParticle()에 추가하는 조건문에 따라 다릅니다. 예외를 던지면 1109가 나오는데, 조건을 완전히 빼면 812가됩니다. "nah"를 사용하면 while 루프가 영원히 실행되고 x ++ 문을 사용하면 세그먼트 오류가 발생합니다. 감사합니다.

+0

나는 당신이 무슨 말을하는지 잘 모르겠다. 'if (startpos> blocklength)'내부에 아무것도 없으면 배열의 데이터를 변경하지만,'throw '를 주석 처리하여 루프를 종료 할 수 없다면 대신'return'을 시도하거나' '그 자체. 당신이 "X를 준다"고 말할 때 당신은 무엇을 의미합니까? –

+0

@RetiredNinja 닫는 괄호를 잊어 버렸습니다. 미안하지만 문제는 if 문 안쪽의 아무 것도 데이터를 변경하지 말아야한다는 것입니다. while 루프는 항상 동일한 startpos 값으로 동일한 파일에 대해 같은 지점에서 멈추어야합니다. while 루프에 if 문을 삽입하면 startpos 값이나 함수 비헤이비어가 변경되고 이유는 알 수 없습니다. –

+0

if 문은 무한 루프를 벗어나는 동시에 주석을 제거하지 않는 한 아무 것도 변경하지 않습니다. 그 값이 파일에 존재하지 않는다고 생각 했습니까? 오른쪽 엔디안 값을 찾으십니까? [여기] (http://coliru.stacked-crooked.com/a/bbf55a3d3d044db6)는 파일의 임의의 위치에 해당 값을 쓰고 다시 찾는 예제입니다. 아마 도움이 될지 모르지만 데이터 파일에 액세스 할 필요없이 추측 이외의 것을 제공 할 수는 없습니다. –

답변

1

입력 내용이 유효한 파일 인 경우 코드가 작동하는 것 같습니다. @RetiredNinja는 지적

는 가능한 문제는 다음과 같습니다

  1. argv [1] 대신 argv [0] 사용.

    argv [0]은 일반적으로 구문 분석하려는 파일이 아닌 실행 파일의 이름을 가리 킵니다. 입자를 찾기 위해 현재 실행중인 실행 파일을 구문 분석하려고하면 잘못된 디자인이됩니다. (Windows 용)

    ./myprogram file.bin 
    

    나 :

    ifstream file(argv[1], ios::binary | ios::ate); 
    

    는 (리눅스 용)이 같은 프로그램을 실행 그래서이 변화 할

    .\myprogram.exe file.bin 
    

    을 또는에서 기본 명령 줄 인수를 변경 프로그램을 디버그하려고한다면 IDE.

  2. 0xFF000000은 정렬 된 4 바이트 경계에 없습니다.

    예를 들어이 값은 배열에있는 두 개의 문자에 분산되어있을 수 있습니다. 이 상황은 좀 더 복잡합니다. 기본적으로 uint32_t 배열을 통해 char*으로 반복하고 0xFF을 찾고(endianness에 따라 다름)을 찾을 수 있는지 확인해야합니다.

나머지 대답은 일부 사소한 권장 사항입니다. 당신이 원한다면 나머지는 무시할 수 있습니다. 아래의 모든 것은 문제 2가 존재하지 않는다고 가정합니다. 자신의 메모리가 불필요 관리

void createBinFile (const std::string &file_name) 
{ 
    // Some random data to use. 
    const uint32_t sample_data [] = { 
     0x000000cc, 
     0x0000dd00, 
     0x00ee0000, 
     0xff000000, 
     0x00000011, 
     0x00002200, 
     0x00330000, 
     0x44000000, 
    } ; 

    // Write some binary data. 
    std::ofstream file (file_name, std::ios::binary) ; 
    file.write (reinterpret_cast <const char *> (sample_data), sizeof (sample_data)) ; 
} 

: 여기

내가 당신의 코드에 대한 테스트 파일을 생성하는 방법이다.

std::vector <uint32_t> loadBinFile (const std::string &file_name) 
{ 
    std::ifstream file (file_name, std::ios::binary | std::ios::ate) ; 

    std::streampos size = file.tellg() ; 
    file.seekg (0, std::ios::beg) ; 

    unsigned padding = (size % sizeof (uint32_t) == 0) ? 0 : 1 ; // or throw exception 
    unsigned vec_size = size/sizeof (uint32_t) + padding ; 

    std::vector <uint32_t> data (vec_size) ; 
    file.read (reinterpret_cast <char*> (&data[0]), size) ; 

    return data ; 
} 

을 그리고 여기 0xFF000000 값을 찾는 방법을 보여줍니다 빠른 드라이버입니다 : 여기에 원시 uint32_t* 배열 대신 std::vector <uint32_t>를 사용하는 방법이다.이 경우 std::find()의 경우 #include <algorithm>이 필요합니다.

int main (int argc, char *argv []) 
{ 
    const std::string file_name = argv [1] ; 

    std::vector <uint32_t> data = loadBinFile (file_name) ; 

    const uint32_t sentry_value = 0xff000000 ; 

    typedef std::vector <uint32_t>::const_iterator const_iterator ; 
    const_iterator citer = std::find (data.begin(), data.end(), sentry_value) ; 

    if (citer != data.end()) { 
     std::cout << "Particle found!" "\n" ; 
    } 

    else { 
     std::cout << "Particle not found!" "\n" ; 
    } 

    return 0 ; 
}