0

I'm using generator to make random sequence of unsigned __int8'ers, and then writing them to file using ofstream.write() with this method;

void CDataGenerator::GenerateRandom(std::string outputFileName, int length, bool UseEntireRange, int max) {
    std::ofstream file;
    file.open(outputFileName, std::ifstream::out | std::ifstream::binary);
    int count = 0;
    unsigned __int8* buf = new unsigned __int8[length];
    while (count < length-1) {
        int number = 0;
        if (UseEntireRange)
            number = rand();
        else {
            int rnd = rand();
            number = (int)((double)rnd / RAND_MAX * max);
        }
        int capacity = 0;
        if (number == 0)
            capacity = 1;
        else
            capacity = (int)(floor(log10(number)) + 1);
        for (int i = 0; i < capacity; ++i) {
            if (count >= length - 2)
                break;
            buf[count] = ((unsigned __int8)(number / (int)pow(10, capacity - i - 1)));
            number %= (int)pow(10, capacity - i - 1);
            ++count;            
        }       
        ++count;
        buf[count] = BCD_SEPARATOR;
    }
    file.write((__int8*)&buf[0], length);
    delete[] buf;
    file.close();   
}

Where const static unsigned __int8 BCD_SEPARATOR = 0xff;

Then I try to read file with following method

unsigned __int8* CModel::GetRawData(std::string inputFileName, int &length) {
    std::ifstream file(inputFileName, std::ifstream::ate | std::ifstream::binary);
    length = file.tellg();
    file.close();
    file.open(inputFileName, std::ifstream::in | std::ifstream::binary);
    unsigned __int8* result = new unsigned __int8[length];
    file.read((__int8*)&result[0], length);
    file.close();
    return result;
}

Im my test generater creates sequence like this 0x0 0xFF 0x5 0x6 0xFF 0x1 0x9 0xFF 0x8 0xFF but from reading stream I get 0x0 0xCD 0x5 0x6 0xCD 0x1 0x9 0xCD 0x8 0xCD sequence. It's obvously that all 0xff are replaced with 0xcd. Is it connected with (__int8*) casts and How do I solve it?

5
  • 1
    When you look at the file in a hex editor, has it been written with the right values? Commented Aug 5, 2016 at 12:01
  • Did you check that the reading or writing succeeded? That opening the file succeeded? Commented Aug 5, 2016 at 12:05
  • Also I suggest you use the standard fixed-width integer types like int8_tfrom <cstdint> instead of the compiler-specific and non-portable __int8. I also recommend against using C-style casts in C++. Instead use something like reinterpret_cast<char*>(result). None of these things should relate to your problem though. Commented Aug 5, 2016 at 12:08
  • @RichardCritten, in hex editor it has wrong values Commented Aug 5, 2016 at 12:20
  • You should probably use a debugger and step through the code writing to the file. Commented Aug 5, 2016 at 12:23

1 Answer 1

3

With knowledge of the CRT debug heap that Visual Studio uses (I'm just assuming you're using Visual Studio), it's a good guess that the 0xCD value is from uninitialized heap memory. The question then becomes: Why are you seeing this in the output? To figure out why, you can simply step through your GenerateRandom function using your debugger/read the code.

From this it becomes apparent where the problem is:

for (int i = 0; i < capacity; ++i) {
    if (count >= length - 2)
        break;
    buf[count] = ((unsigned __int8)(number / (int)pow(10, capacity - i - 1)));
    number %= (int)pow(10, capacity - i - 1);
    ++count; //Increment count ONCE
}

++count; //Increment count a SECOND time
buf[count] = BCD_SEPARATOR;

The problem is that when the program leaves the for-loop shown here, count will already have been incremented once, so your "count" is already at your next uninitialized __int8 in the buffer. You then increment "count" once again before writing BCD_SEPARATOR to the "count" position in the buffer. This results in the program skipping the position where you actually want your BCD_SEPARATOR.

The next problem then becomes that, because you don't increment "count" between after you write the BCD_SEPARATOR to the buffer and the next time you enter the for-loop shown above, you immediately overwrite the BCD_SEPARATOR.

A solution to the problem could be to simply swap things around like this:

buf[count] = BCD_SEPARATOR;
++count;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.