Inconsistent Binary Data or Condition Statement Changing Data

╄→гoц情女王★ 提交于 2019-12-11 05:06:41

问题


Really having some trouble even phrasing the problem. What's happening is I'm reading and storing an entire binary file into a uint32_t*. Then checking for the start of the segment of data I need. However, adding a check to just make sure I haven't passed over the array changes where the start of the segment is and I have no idea why.

#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 then varies depending on what condition statement I add into NewParticle(), eg. throwing the exception gives 1109 where as taking the condition out completely gives 812. Using the "nah" makes the while loop run forever and using the x++ statement causes a segment fault... Any idea how these could possibly be changing things? Thank you


回答1:


You code seems to work if your input is a valid file.

As @RetiredNinja pointed out, possible problems are:

  1. Using argv [0] instead of argv [1].

    argv [0] will typically point to the name of the executable, which is probably not the file you wish to parse. If you are trying to parse your currently running executable to find your particles, then you have a bad design. So make this change:

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

    Run your program like this (for Linux):

    ./myprogram file.bin
    

    or (for Windows):

    .\myprogram.exe file.bin
    

    Or change the default command line arguments in your IDE if you're trying to debug your program.

  2. The value 0xFF000000 is not on an aligned four-byte boundary.

    For instance, the value could be spread across two uint32_ts in your array. This situation is a bit more complicated. You will have to basically iterate through your uint32_t array with a char* and look for a 0xFF and see if you can find 3 0x00 before or after it (depending on endianness).

The rest of this answer is just some minor recommendations. You can ignore the rest of this if you want. All of this below assumes problem 2 does not exist.

Here is how I generated a test file for your code:

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)) ;
}

Managing your own memory is unnecessary. Here's a way to use a std::vector <uint32_t> instead of a raw uint32_t* array:

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 ;
}

And here's a quick driver that shows how to find your 0xFF000000 value. This requires you to #include <algorithm> for std::find().

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 ;
}


来源:https://stackoverflow.com/questions/24086211/inconsistent-binary-data-or-condition-statement-changing-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!