Reading int value from char array after converting to void pointer - c++

I'm trying to build memory chunks of generic data types, but I'm getting garbage when printing the result.
void Read(void* _data, size_t _size, int _position) const
{
char* data = new char[_size];
memcpy(data, m_data + _position - _size, _size);
}
void Write(void* _data, size_t _size, int _position)
{
char* data = new char[_size];
memcpy(m_data + _position, data, _size);
return 1;
}
int main()
{
Chunk c(10);
int value = 10, result;
c.Write(&value, sizeof(int), 0);
c.Read(&result, sizeof(int), sizeof(int));
cout << *((int *)result) << endl;
return 0;
}
What am I doing wrong?

"What am I doing wrong?" - Pretty much everything:
To begin with, both Read and Write functions end with a memory leak, as the allocated-memory pointed by the data local variable is "lost" (no one "knows" the address after the function returns).
In addition, what exactly are you expecting to get by casting (int*)result? It is most certainly not going to be a valid memory address which you can then safely dereference using *((int*)result).

In your read function, the parameter _data is not used, so it won't modify anything. It should be:
void Read(void* _data, size_t _size, int _position)
{
memcpy(_data, m_data + _position - _size, _size);
}
Also, the code to output variable result doesn't make sense, should just be:
cout << result << endl;
As the program is not the complete program, I don't know if there're still other errors

Related

why strcat_s causing problems

I'm facing problem that I get random chars output instead of getting first and mid and last name combined which is the purpose of the program and when I run the debugger it says that the problem in strcat_s but I don't know what's the problem with it
#include <iostream>
#include <string.h>
class name {
private:
char first[20], mid[20], last[20];
public:
name();
name(const char*, const char*, const char*);
~name();
char* show();
};
name::name()
{
first[0] = mid[0] = last[0] = '\0';
}
name::name(const char* f, const char* m, const char* l)
{
size_t lenF = strlen(f), lenM = strlen(m), lenL = strlen(l);
if (strlen(f) > 20) lenF = 20;
else if (strlen(m) > 20) lenM = 20;
else if (strlen(l) > 20) lenL = 20;
strncpy_s(first, f, lenF);
strncpy_s(mid, m, lenM);
strncpy_s(last, l, lenL);
}
name::~name()
{
std::cout << "distructing..." << std::endl;
}
char* name::show()
{
char temp[62];
strcpy_s(temp, first);
strcat_s(temp, " ");
strcat_s(temp, mid);
strcat_s(temp, " ");
strcat_s(temp, last);
return temp;
}
int main()
{
name a("kinan", "fathee", "ayed");
std::cout << a.show() << std::endl;
}
Your logic for returning the full name is incorrect. You have a local variable temp and you are returning a reference to that variable. However, this variable is destroyed once show() function is completed. So, in your main function you have a reference but its pointing to something that is already destroyed. That's why you will see random characters when you print it. Here is the solution to your problem. You need to create a dynamic array i.e a pointer so that it does not get destroyed.
char *name::show()
{
int size = strlen(first) + strlen(mid) + strlen(last) + 3;
char *temp = new char[size];
strcpy_s(temp, size, first);
strcat_s(temp, size, " ");
strcat_s(temp, size, mid);
strcat_s(temp, size, " ");
strcat_s(temp, size, last);
return temp;
}
int main()
{
name a("kinan", "fathee", "ayed");
char *temp = a.show();
std::cout << temp << std::endl;
delete[] temp;
}
Edit: In your original code, if you print temp at the end of show function before returning it, you will see that temp contains full name.
Edit: Temp is a local variable. Every local variable is destroyed at the end of the function's execution. In the suggested solution, I am creating an array dynamically on the heap. When we dynamically create an array, it's not removed from the heap automatically. So, when I return a reference to that array and use it in main it still works.
Edit:
I have added delete[] in main function to deallocate memory.
Should be reserved 1 character for '\0', therefore you need to write strncpy_s(first, f, lenF - 1);

arithmetic std::unique_ptr and void* (get position of element by address)

I have a class:
Allocate blockSize*maxSize bytes of memory. Has a method which return ptr to free block of memory.
I fill this block in main() for example (see usage below) and send it back to my class.
PROBLEM: How can I get position of sent me back address of initialized data? Because in main() I have void* ptr, not std::unique_ptr, and arithmetic with method memoryPool.get() not possible to use.
class A {
private:
size_t maxBlocks;
size_t blockSize;
std::unique_ptr<unsigned char[]> memoryPool;
void *getObjPtr(const size_t pos) const {
return reinterpret_cast<void *>(memoryPool.get() + pos * blockSize);
}
public:
A(size_t blockSize, size_t maxBlocks) : blockSize(blockSize), maxBlocks(maxBlocks),
memoryPool(new unsigned char[maxBlocks * blockSize]) {}
void *getFree() {
for (size_t i = 0; i < maxBlocks; ++i) {
//check if this block not use (I cut this part)
return getObjPtr(i);
}
}
size_t getPosition(void *data) {
//how can I get position of element?
// auto pos = ((char*)data - memoryPool.get()) / blockSize; - not works
// ok there should be C++ style reinterpret_cast, but to short code I skip it
}
}
Example of usage:
int main() {
A queue(sizeof(int), 10);
int *a = static_cast<int *>(queue.getFree());
*a = 4;
auto pos = queue.getPosition(a);//want to get position
}
What is proper way to do it? Without using std::unique_ptr in main?
When I compile your code with Visual C++ 2019, I get this error:
error C2440: '-': cannot convert from 'unsigned char *' to 'char *'
If I change your code to cast to unsigned char* as per the error message, then it compiles:
auto pos = ((unsigned char*)data - memoryPool.get()) / blockSize;
Whether that does what you intend - well, it appears to, but you haven't clearly specified what getPosition does, so I can only guess.
Please post the error message in the future, not just say it doesn't work! It'll help us help you.

Get int from byte array by offset

I am new to C++. Can't get int from byte array by offset.
When i read directly from memory all works fine and i am gettings 100 - this is correct value
int base = 0x100;
int offset = 0x256;
int easy = memory->ReadMemory<int>(base + offset); // easy = 100
But if i try to get a chunk of bytes and read from them, here problem comes
template<class T>
T FromBuffer(uint8_t* buffer, size_t offset)
{
T t_buf = 0;
memcpy(&t_buf, buffer + offset, sizeof(T));
return t_buf;
}
uint8_t* ReadBytes(DWORD Address, int Size)
{
auto arr = new uint8_t[Size];
ReadProcessMemory(TargetProcess, (LPVOID)Address, arr, sizeof(arr), 0);
return arr;
}
auto bytes = memory->ReadBytes(base, 2500);
int hard = *((unsigned int *)&bytes[offset]); // hard = -842150451
uint32_t hard2 = memory->FromBuffer<uint32_t>(bytes, offset); // hard2 = 3452816845
With C# it would easy like this
int hard = BitConverter.ToInt32(bytes, offset);
Converting this type of C# code to C++ doesn't make any sense, you were forced to do some whacky stuff in C# because doing this type of operation is not what C# was intended for.
You do not need to create a dynamic buffer and do any of that wizardry. Just do:
template <class T>
T RPM(void* addr)
{
T t;
ReadProcessMemory(handle, addr, &t, sizeof(t), nullptr);
return t;
}
int RPM(addr + offset);

Difficulties deleting memory

I'm having some trouble working with memory: I have to keep a copy of some data in a new class. The main problem is that the first 9 bytes of this data should be thrown away. Whenever the object gets deleted though, I either get a segmentation fault or SIGABRT (it's not even consistent)
class Frame
{
public:
Frame();
~Frame();
void setFirstData(uint8_t *data, size_t dataLength);
void setSecondData(uint8_t *data, size_t dataLength);
void setThirdData(uint8_t *data, size_t dataLength);
void setFourthData(uint8_t *data, size_t dataLength);
...
private:
unsigned char *_firstData;
bool _firstDataSet;
size_t _firstDataLength;
unsigned char *_secondData;
bool _secondDataSet;
size_t _secondDataLength;
unsigned char *_thirdData;
bool _thirdDataSet;
size_t _thirdDataLength;
unsigned char *_fourthData;
bool _fourthDataSet;
size_t _fourthDataLength;
};
Frame::Frame()
{
_firstDataSet = false;
_secondDataSet = false;
_thirdDataSet = false;
_fourthDataSet = false;
}
Frame::~Frame()
{
if (_firstDataSet)
delete [] _firstData;
if (_secondDataSet)
delete[] _secondData;
if (_thirdDataSet)
delete[] _thirdData;
if (_fourthDataSet)
delete[] _fourthData;
}
void Frame::setFirstData(uint8_t *data, size_t dataLength)
{
//copy all the data in a unsigned char*, except for the first 9 bytes
_firstDataLength = dataLength - 9;
_firstData = new unsigned char[_firstDataLength];
memcpy(_firstData, data + 9, _firstDataLength*sizeof(*_firstData));
/*for (int i = 0; i < dataLength - 9; i++)
{
_firstData[i] = (unsigned char) data[i + 9];
}*/
_firstDataSet = true;
}
The other setData functions are identical to setFirstData, but with the correct arrays.
Am I supposed to use something else than memcpy? Or is the usage wrong? The commented for loop was my original method of 'copying' the data but I dont think it actually copies the data (original array will be deleted when the copied data still has to be available).
EDIT: I added the qt tag because i'm working in a Qt environment and using some Qt classes for GUI. I don't think qt has anything to do with these basic C++ functions.
What with setting firstData:
_firstData = new unsigned char[_dataLength];
memcpy(_firstData, data + 9, _dataLength*sizeof(*_firstData));

How to cast from char pointer to custom object pointer

I'm using leveldb to store key-value pairs of integer and MyClass objects. Actually, a key can contain more then one of theses objects.
The problem I have appears when retrieving the data from the database. It compiles, however the values of the MyClass members are not the one I put into the database.
std::string value;
leveldb::Slice keySlice = ANYKEY;
levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
The std::string value1 can now contain only one MyClass object or more. So how do I get them?
I already tried the following which didn't work;
1.) directly typecasting and memcpy
std::vector<MyClass> vObjects;
MyClass* obj = (MyClass*)malloc( value.size());
memcpy((void*)obj, (void*) (value.c_str()), value.size());
MyClass dummyObj;
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
dummyObj = *(obj+i);
vObjects.push_back(dummyObj);
}
2.) reinterpret_cast to void pointer
MyClass* obj = (MyClass*)malloc( value.size());
const void* vobj = reinterpret_cast<const void*>( value.c_str() );
int numValues = value.size()/sizeof(MyClass);
for( int i=0; i<numValues; ++i) {
const MyClass dummyObj = *(reinterpret_cast<const MyClass*>(vobj)+i);
vObjects.push_back(dummyObj);
}
MyClass is a collection of several public members, e.g. unsigned int and unsigned char and it has a stable size.
I know that there are similar problems with only one object. But in my case the vector can contain more then one and it comes from the leveldb database.
EDIT: SOLUTION
I wrote (de)serialization method for MyClass which then made it working. Thanks for the hint!
void MyClass::serialize( char* outBuff ) {
memcpy(outBuff, (const void*) &aVar, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy(outBuff+c, (const void*) &bVar, sizeof(bVar));
c += sizeof(bVAr);
/* and so on */
}
void MyClass::deserialize( const char* inBuff ) {
memcpy((void*) &aVar, inBuff, sizeof(aVar));
unsigned int c = sizeof(aVar);
memcpy((void*) &aVar, inBuff+c, sizeof(aVar));
c += sizeof(aVar);
/* and so on */
}
The get method is as follows (put analogously):
int getValues(leveldb::Slice keySlice, std::vector<MyObj>& values) const {
std::string value;
leveldb::Status status = levelDBObj->Get(leveldb::ReadOptions(), keySlice, &value);
if (!status.ok()) {
values.clear();
return -1;
}
int nValues = value1.size()/sizeof(CHit);
MyObj dummyObj;
for( int i=0; i<nValues; ++i) {
dummyObj.deserialize(value.c_str()+i*sizeof(MyObj));
values.push_back(dummyObj);
}
return 0;
}
You have to serialize your class... otherwise, you're just taking some memory and writing it in leveldb. Whatever you get back is not only going to be different, but it will probably be completely useless too. Check out this question for more info on serialization: How do you serialize an object in C++?
LevelDB does support multiple objects under one key, however, try to avoid doing that unless you have a really good reason. I would recommend that you hash each object with a unique hash (see Google's CityHash if you want a hashing function) and store the serialized objects with their corresponding hash. If your objects is a collection in itself, then you have to serialize all of your objects to an array of bytes and have some method that allows you to determine where each object begins/ends.
Update
A serializable class would look something like this:
class MyClass
{
private:
int _numeric;
string _text;
public:
// constructors
// mutators
void SetNumeric(int num);
void SetText(string text);
static unsigned int SerializableSize()
{
// returns the serializable size of the class with the schema:
// 4 bytes for the numeric (integer)
// 4 bytes for the unsigned int (the size of the text)
// n bytes for the text (it has a variable size)
return sizeof(int) + sizeof(unsigned int) + _text.size();
}
// serialization
int Serialize(const char* buffer, const unsigned int bufferLen, const unsigned int position)
{
// check if the object can be serialized in the available buffer space
if(position+SerializableSize()>bufferLen)
{
// don't write anything and return -1 signaling that there was an error
return -1;
}
unsigned int finalPosition = position;
// write the numeric value
*(int*)(buffer + finalPosition) = _numeric;
// move the final position past the numeric value
finalPosition += sizeof(int);
// write the size of the text
*(unsigned int*)(buffer + finalPosition) = (unsigned int)_text.size();
// move the final position past the size of the string
finalPosition += sizeof(unsigned int);
// write the string
memcpy((void*)(buffer+finalPosition), _text.c_str(), (unsigned int)_text.size());
// move the final position past the end of the string
finalPosition += (unsigned int)_text.size();
// return the number of bytes written to the buffer
return finalPosition-position;
}
// deserialization
static int Deserialize(MyClass& myObject,
const char* buffer,
const unsigned int buffSize,
const unsigned int position)
{
insigned int currPosition = position;
// copy the numeric value
int numeric = *(int*)(buffer + currentPosition);
// increment the current position past the numeric value
currentPosition += sizeof(int);
// copy the size of the text
unsigned int textSize = *(unsigned int*)(buffer + currentPosition);
// increment the current position past the size of the text
currentPosition += sizeof(unsigned int);
// copy the text
string text((buffer+currentPosition), textSize);
if(currentPosition > buffSize)
{
// you decide what to do here
}
// Set your object's values
myObject.SetNumeric(numeric);
myObject.SetText(text);
// return the number of bytes deserialized
return currentPosition - position;
}
};