0

tl;dr : How to convert an unsigned 32-bit integer to chars/uint8_t without random text

Okay, I am willing to sacrifice several reputation points for this. I need to quickly convert a 4-byte unsigned integer to array bytes in order to read/write/manipulate binary files of my own structure.
So that I can read a structure and then use it as an object, instead of reading it, writing in it for each an every change.

But when I try to implement a function I get a leakage. Pointer just keeps adding the values outside the scope of the function.

void trans_byte( uint32_t &A, uint8_t *out ){
    // i did this with loop too same thing happens
    uint8_t *ptr = (uint8_t*)&A;
    out[3] = *ptr;
    ptr++;
    out[2] = *ptr;
    ptr++;
    out[1] = *ptr;
    ptr++;
    out[0] = *ptr;
    ptr = ptr - 4;
}

uint32_t trans_ray( uint8_t *in ){
    return ( in[0] << 24 ) | ( in[1] << 16 ) | ( in[2] << 8 ) | in[3]; 
}

And in main :

int main(){
    std::cout << "SHUGA" << std::endl; // test printing to see if test works 

    uint32_t ADR = 0x6D4E4344; // memory should write magic of mNCD

    uint8_t ret[4];// array to be "outed" from function
    trans_byte(ADR, ret); // function
    uint8_t ret2[4] = { ret[0], ret[1], ret[2], ret[3] }; //copy of array to see if issue happens if i copy it

    std::cout << ret << std::endl; // printing the array 1
    std::cout << ret2 << std::endl; // printing the array 2
}

And output :

SHUGA
mNCDmNCD // keep in mind I called the function only once. 
mNCD

After I add to the main

std::cout << "shiya" << std::endl;
uint32_t ADR2 = trans_ray(ret);

std::cout << ret << std::endl;
std::cout << ret2 << std::endl;
std::cout << (ret==ret2) << std::endl;

And then I get this lovely mess:

SHUGA
mNCDmNCD─[uÉ@
mNCD─[uÉ@
shiya
mNCDmNCD─[uÉ@
mNCD─[uÉ@
0

So I am guessing that this is some sort of memory leak, and pointer keeps reading memory or something later on ( and therefore a plethora of symbols ).

So, how can I do this back and forth conversions from uint32_t to uint8_t without pointer continuing to read and manipulate an array even if it isn't called?

Before you start commenting:
I don't want to use std::vector since I don't want to add another 20kb or so of binary data per file to the existing large project be it file or PE.
I can't use std::string since I don't want to hunt for string ends \x00.
I tried using unions, but bytes are reversed, and for magic numbers and similar I need them to be in order. And even if I try to reverse the array I still need to run onto this issue.
I tried using struct-ures and class-es, but when I change something in object and I need to update the file, I still end up with this issue when writing code block.

Akash Mahapatra
  • 2,988
  • 1
  • 14
  • 28
Danilo
  • 1,017
  • 13
  • 32
  • 2
    *`uint8_t *ptr = (uint8_t*)&A;`* – Strict aliasing violation. – Swordfish May 05 '19 at 15:59
  • ok, what do you suggest that i correct it ? – Danilo May 05 '19 at 16:01
  • 1
    Use a pointer type that is allowed to alias other types. Pick your weapon: `char`, `unsigned char`, or `std​::​byte`. See also [Ramblings about `uint8_t` and Undefined Behaviour](https://gist.github.com/jibsen/da6be27cde4d526ee564). Also [there](https://stackoverflow.com/a/43551805/3975177) for C++. – Swordfish May 05 '19 at 16:05
  • @Swordfish Isn't (usually) `uint8_t` alias for `unsigned char`? So there is no aliasing violation. Nevermind, you just added link that answers it. – R2RT May 05 '19 at 16:08
  • `uint8_t` is optional. If it cannot be provided, a system with a 9 bit byte, for example, it should not be implemented and you should get a compiler error. – user4581301 May 05 '19 at 16:24
  • @R2RT maybe, maybe not. – Swordfish May 05 '19 at 16:24

2 Answers2

2
 std::cout << ret

This requires a null terminated string (info here):

8) Outputs an implementation-defined string as if by *this << s, where s is a null-terminated character type string.

Otherwise it will keep printing until \0 is found.

That is why we use vector, string etc. To forget all this C-style 1980's programming. Unless you are programming some super microcontroller with 20KB RAM then memory should not be an issue.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
1

How to convert unsigned 32 bit integer to chars/uint8_t without random text

You can union for this but you have to read about Endianness. Try this:

#include <stdint.h>

union {
    uint32_t _32ui;
    uint8_t _8ui[4];
}

I tried using unions, but bytes are reversed, and for magic numbers and similar I need them to be in order. And even if I try to reverse the array I still need to run onto this issue.

There are functions for converting the uint32_t in big-endian or little-endian order. I am not sure about your Operating System, processor and compiler. But there are functions like htonl available for Linux.

So I am guessing that this is some sort of memory leak, and pointer keeps reading memory or something later on ( and therefore a plethora of symbols ).

No. It is not the issue. You aren't allocating any memory in your program that would cause any memory leak nor you are going past your allocated memory buffer. The problem is that you haven't gone through std::cout documentation and you might have ignored your compiler's warnings.

std::cout has been overloaded for C-Style Strings and it expects null-terminated character array. But you haven't provided it Null-terminated character array. I would suggest to write a simple function to print your array.

void printArray(uint8_t *array, size_t size)
{
    for (size_t i = 0; i < size; i++)
        std::cout << array[i];
    std::cout << std::endl;
}
abhiarora
  • 9,743
  • 5
  • 32
  • 57
  • 3
    Setting one member of a `union` and then reading another invokes undefined behaviour. This sits in the pile of tricks that probably works but is not guaranteed. – user4581301 May 05 '19 at 16:18