Run std::function getted by binary read - c++

I'm developing a application and my idea is store "apps" in files, like executables. Now i have that:
AppWriter.c
#include <vector>
#include <time.h>
#include <functional>
struct PROGRAM
{
std::vector<int> RandomStuff;
std::vector<std::function<void()>> Functions;
std::function<void()> MAIN;
} CODED;
void RANDOMFUNC()
{
srand(time(NULL));
for(int i = 0; i < 40; i++)
CODED.RandomStuff.push_back(rand() % 254);
}
void LOGARRAY()
{
for(int i = 0; i < CODED.RandomStuff.size(); i++)
std::cout << "["<< i + 1 <<"]: "<< CODED.RandomStuff[i] << std::endl;
}
void PROGRAMMAIN()
{
std::cout << "Hello i call random function!" << std::endl;
CODED.Functions[0]();
CODED.Functions[1]();
}
void main()
{
CODED.MAIN = PROGRAMMAIN;
CODED.Functions.push_back(RANDOMFUNC);
CODED.Functions.push_back(LOGARRAY);
std::cout << "Testing MAIN" << std::endl;
CODED.MAIN();
FILE *file = fopen("TEST_PROGRAM.TRI","wb+");
fwrite(&CODED,sizeof(CODED),1,file);
fclose(file);
std::cout << "Program writted correctly!" << std::endl;
_sleep(10000);
}
AppReader.c
#include <iostream>
#include <vector>
#include <time.h>
#include <functional>
struct PROGRAM
{
std::vector<int> RandomStuff;
std::vector<std::function<void()>> Functions;
std::function<void()> MAIN;
} DUMPED;
void main()
{
FILE *file = fopen("TEST_PROGRAM.TRI","rb+");
fseek(file,0,SEEK_END);
int program_len = ftell(file);
rewind(file);
fread(&DUMPED,sizeof(PROGRAM),1,file);
std::cout
<< "Function array size: " << DUMPED.Functions.size() << std::endl
<< "Random Stuff Array size: " << DUMPED.RandomStuff.size() << std::endl;
DUMPED.MAIN();
}
When i run AppReader the functions dont work(Maybe why std::function it's like void pointers?), but in arrays or if i add variables i can see with debugger the data are storaged correctly (for that i tryed the vector of functions), but whatever doesn't work throw's me error on functional file. ¿Any ideas how i can do that?

This is never going to work. At all. Ever. std::function is a complex type. Binary reads and writes don't work for complex types. They never can. You would have to ask for functions in a pre-defined serializable format, like LLVM IR.

Your problem is that you're storing information about functions that exist in one executable, then trying to run them in a separate executable. Other than that, your code does work, but as DeadMG says, you shouldn't be storing complex types in a file. Here's how I modified your code to prove that your code works if run within a single executable:
#include <iostream>
#include <vector>
#include <time.h>
#include <functional>
struct PROGRAM
{
std::vector<int> RandomStuff;
std::vector<std::function<void()>> Functions;
std::function<void()> MAIN;
} CODED;
void RANDOMFUNC()
{
srand(time(NULL));
for(int i = 0; i < 40; i++)
CODED.RandomStuff.push_back(rand() % 254);
}
void LOGARRAY()
{
for(int i = 0; i < CODED.RandomStuff.size(); i++)
std::cout << "["<< i + 1 <<"]: "<< CODED.RandomStuff[i] << std::endl;
}
void PROGRAMMAIN()
{
std::cout << "Hello i call random function!" << std::endl;
CODED.Functions[0]();
CODED.Functions[1]();
}
int main()
{
CODED.MAIN = PROGRAMMAIN;
CODED.Functions.push_back(RANDOMFUNC);
CODED.Functions.push_back(LOGARRAY);
std::cout << "Testing MAIN" << std::endl;
CODED.MAIN();
FILE *file = fopen("TEST_PROGRAM.TRI","wb+");
fwrite(&CODED,sizeof(CODED),1,file);
fclose(file);
std::cout << "Program writted correctly!" << std::endl;
// _sleep(10000);
std::cout << "---------------------\n";
file = fopen("TEST_PROGRAM.TRI","rb+");
fseek(file,0,SEEK_END);
int program_len = ftell(file);
rewind(file);
fread(&CODED,sizeof(PROGRAM),1,file);
std::cout
<< "Function array size: " << CODED.Functions.size() << std::endl
<< "Random Stuff Array size: " << CODED.RandomStuff.size() << std::endl;
CODED.MAIN();
}
The problem is not that you're storing complex types via binary read/write, per se. (Although that is a problem, it's not the cause of the problem you posted this question about.) Your problem is that your data structures are storing information about the functions that exist in your 'writer' executable. Those same functions don't even exist in your 'reader' executable, but even if they did, they likely wouldn't be at the same address. Your data structures are storing, via std::function, pointers to the addresses where the functions exist in your 'writer' executable. When you try to call these non-existent functions in your 'reader' executable, your code happily tries to call them but you get a segfault (or whatever error your OS gives) because that's not the start of a valid function in your 'reader' executable.
Now with regard to writing complex types (e.g. std::vector) directly to a file in binary format: Doing so "works" in the sample code above only because the binary copies of the std::vectors have pointers that, once read back in, still point to valid data from the original std::vectors which you wrote out. Note that you didn't write the std::vector's actual data, you only wrote their metadata, which probably includes things like the length of the vector, the amount of memory currently allocated for the vector, and a pointer to the vector's data. When you read that back, the metadata is correct except for one thing: Any pointers in it are pointing to addresses that were valid when you wrote the data, but which may not be valid now. In the case of the sample code above, the pointers end up pointing to the same (still valid) data from the original vectors. But there's still a problem here: You now have more than one std::vector that thinks they own that memory. When one of them is deleted, it will delete the memory that the other vector expects to still exist. And when the other vector is deleted, it will cause a double-delete. That opens the door to all kinds of UB. E.g. that memory could have been allocated for another purpose by that time, and now the 2nd delete will delete that other purpose's memory, or else the memory has NOT been allocated for another purpose and the 2nd delete may corrupt the heap. To fix this, you'd have to serialize out the essence of each vector, rather than their binary representation, and when reading it back in, you'd have to reconstruct an equivalent copy, rather than simply reconstitute a copy from the binary image of the original.

Related

Is it possible to bind a function from a vector of objects to a std::function, or how would you access a function from a vector of objects this way

I have a two classes, one of which is a 'main' configuration, the other is a secondary configuration with a subset of some options from the main configuration. One of the 'main' configuration members is a vector of secondary configuration objects used to override the main configuration options if present. I can bind the 'main' configurations get methods to functions which I add to a vector and use to get those parameters in testing (not all options are tested every time, so I create a vector of set values which matches the vector of get methods which I compare.)
I would like to similarly bind the get methods from the secondary configurations, specifically the last (should be only) one in the vector, but I am unsure how to do this or if it is even possible. I have tried a number of tweaks that make sense to me, however I am starting to doubt if this would even be a good idea with the amount of convolution I am creating. If anyone could point me to how I would accomplish this, either by binding it in such a way that it calls the desired method from the first object in the vector or another way, that is what I am looking for. A heavily paired down example of what I am attempting to do is below.
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
class secConfig{
private:
double data;
public:
secConfig(double);
double get_data();
};
secConfig::secConfig(double indata){
data = indata;
}
double secConfig::get_data(){
return data;
}
class config{
private:
std::vector<secConfig> secConfigs;
double normalData;
public:
config(double, vector<secConfig>);
double getData();
vector<secConfig> getVecData();
};
config::config(double inData, vector<secConfig> inVec){
normalData = inData;
secConfigs = inVec;
}
double config::getData(){
return normalData;
}
vector<secConfig> config::getVecData(){
return secConfigs;
}
int main(int argc, char const *argv[])
{
secConfig initial(66.6);
vector<secConfig> inConfigs;
inConfigs.push_back(initial);
cout << "Inconfig raw data: " << initial.get_data() << endl;
cout << "Inconfig vector data: " << inConfigs.back().get_data() << endl;
config mainConfig(55.5, inConfigs);
cout << "Main config raw data: " << mainConfig.getData() << endl;
cout << "Main config internal vec data: " << mainConfig.getVecData().back().get_data() << endl;
vector<function<double()>> getvals;
getvals.push_back(bind(&config::getData, &mainConfig));
cout << "Main config bound data: " << getvals[0]() << endl;
// Something like: getvals.push_back(bind(&config::getVecData::back::get_data, &mainConfig));
// So I can: cout << "Secondary (vectorized) config data : " << getvals[1]() << endl;
return 0;
}
std::bind is rarely the best or easiest way to achieve something.
Use a lambda instead.
getvals.push_back( [&]{ return mainConfig.getVecData().back().get_data(); } );

Allocating Dynamic Memory to PlayerID

For hours now I've been trying to work out to how I can assign dynamic memory to a certain playerid, when they join a server, and destroy it when they leave.
I've tried numerous things, I've tried making an array of pointers... which would allow me to access the information with the player ID using the pointer and array position:
int *pInfo[MAX_PLAYERS]; // Global
//Function Local
CPlayers p;
pInfo[playerid] = p;
Which doesn't work, it tells me it cannot convert the class initialisation to a memory pointer.
I tried the same thing, with this line instead:
std::unique_ptr<CPlayers> pInfo[playerid];
However it needs a constant expression where playerid is, this means I cannot do this unless I know what the player ID is and enter it directly... which is impossible as I won't know until they client tries to connect.
Does anyone have a solution that will allow me to make memory dynamically, and have this memory accessible via the playerid. Or some other fashion, that me indefinitely use that clients information in game.
As I have ran out of ideas... I can't find anything online. I'm new as well so there may be functions I've over looked.
Thanks.
You can use MAP container to do that. The ideia is that you have 2 values. The first one is the playerID and the second one, a dynamic memory reference, which contains its properties. Following is a simple example to prove the concept.
#include <map>
#include <memory>
#include <iostream>
int main()
{
std::map<int, std::unique_ptr<int>> pinfo;
// Inserting some elements.
pinfo.emplace(1, std::unique_ptr<int>(new int{3}));
pinfo.emplace(800, std::unique_ptr<int>(new int{700}));
for (auto& i: pinfo)
std::cout << "Player " << i.first << ", value " << *i.second.get() << std::endl;
// Deleting. Note that, due unique_ptr, the memory is deallocated automatically
pinfo.erase(1);
std::cout << "Player 1: deleted" << std::endl;
for (auto& i: pinfo)
std::cout << "Player " << i.first << ", value " << *i.second.get() << std::endl;
}

How to put constants in code memory

I need to keep some information about each function in my program in the form of a constant number. I was wondering if it is possible to put the constant for a function just before it in the code memory, so if a function is called through a function pointer, that information could be read by subtracting the value of the function pointer.
To illustrate further, my code memory should look as follows.
ConstantForFunc1
Func1:
....
ConstantForFunc2
Func2:
....
And following is an example code of how I would read that information
FuncPointer f = &Func2;
int constantForFunc2 = *((int*)(f - sizeof(int)));
And note that using Hash tables is too slow for what I'm trying to achieve, so I need a very fast method. And all this modification, which is inserting constants and code to read from them is done by a compiler pass, which I'm writing and which modifies the LLVM IR. Using structures would be too cumbersome for the compiler pass, as it would have to modify a lot of code.
What you are doing doesn't make sense, yet:
You could use structs maybe?
struct example
{
int constantForFunc;
void (*ptrToFunc)();
};
//After declaring, maybe 3, functions
struct example funcList[3] = {{5, &func1}, {10, &func2}, {15, &func3}};
int currentFuncConstant=funcList[1].constantForFunc;
(*funcList[1].ptrToFunc)();
I haven't used function pointers to be honest, probaby has mistakes.
Is this not acceptable at all?:
#include <iostream>
using namespace std;
const int Const__Fxn1 = 1;
void Fxn1()
{
cout << "Fxn1" << endl;
}
const int Const__Fxn2 = 2;
void Fxn2()
{
cout << "Fxn2" << endl;
}
#define GetFxnConst(FxnName) Const__ ## FxnName
int main()
{
cout << GetFxnConst(Fxn1) << endl;
cout << GetFxnConst(Fxn2) << endl;
return 0;
}
Option 2:
#include <iostream>
#include <cstring>
using namespace std;
const volatile int v1 = 0;
volatile unsigned v2 = 0;
void Fxn1()
{
if (v1) { v2 = 0x12345601; }
cout << "Fxn1" << endl;
}
void Fxn2()
{
if (v1) { v2 = 0x12345602; }
cout << "Fxn2" << endl;
}
int FindFxnConst(void(*f)())
{
const unsigned char* p = (const unsigned char*)f;
while (memcmp(p, "\x56\x34\x12", 3))
p++;
return p[-1];
}
int main()
{
Fxn1();
cout << FindFxnConst(Fxn1) << endl;
Fxn2();
cout << FindFxnConst(Fxn2) << endl;
return 0;
}
Output (Ideone):
Fxn1
1
Fxn2
2
You can embed more than 8 bits of data per function by using other magic prefixes, e.g.:
if (v1)
{
v2 = 0x12345611; // byte 1
v2 = 0x789ABC22; // byte 2
v2 = 0xDEF01233; // byte 3
v2 = 0xFEDCBA44; // byte 4
}
This is not necessarily a reliable solution, let alone portable.
Since the addresses of the functions are known from the executable binary (unless they are loaded from a shared library ofcourse), if you have the address space layout randomization (ASLR) off, you could use gperf to generate a highly efficient hash function for you and use that hash function to get the constants for each function.
However, for this, you will have to compile your program twice, first to get the addresses of the functions from the generated binary, so that you could give those addresses as an input to gperf and recompile using the hash function generated by gperf. But you have to be careful that the addresses of the functions from the first compilation do not become different in the second compilation. I am not sure, how to achieve that.
An alternative, would be to do something like gperf just after your program is loaded, so you don't have to compile twice. But I don't know how to do that.

Trying to initialize a list with values but not working when I use a variable to create the size

This is my second time using C++ and I'm trying to port some Java code I made but am having trouble understanding some behavior. I have a list of data and want to create another list of the same size but the values are default to zero(in Java I use Arrays.fill(list, 0); after creating it). When I try to do something similar in C++ I get variable-sized object 'list1' may not be initialized
Here's a code to better example:
#include <iostream>
#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace std;
using namespace boost::assign;
int main()
{
cout << "Hello World!" << endl;
vector<short> data;
data += -40, -30,-10, 20, 50;
//int coeff [data.size()];
cout << "data array size is " << data.size() << endl;
short list1 [data.size()] = {0}; //does not work
for (int i =0; i<data.size(); i++) {
cout << "data is " << list1[i] << endl;
}
cout << "********** try 2 **************" << endl;
//this works if I use a actual number to create the list but I want to declare it at runtime
short list2 [5] = {0};
for (int ii=0;ii<5;ii++) {
cout << "data is " << list2[ii] << endl;
}
return 0;
}
Like I mentioned, I'm completely green when I comes to C++ (I have read a book and done a few tutorials) so I may be doing something completely wrong. In the event I cannot do this at runtime and only at compile time, is there something else I can use to get the same result?
c++ does not have dynamically sized arrays, so this is illegal:
short list1 [data.size()];
but you can use a vector:
std::vector<short> list1(data.size(),0);
That creates a vector of the same length as data, full of zeroes.
If you want an array whose size is determined at runtime, you'll have to allocate it.
short * list1 = new short[data.size()];
//do stuff
delete [] list1; //we don't want to leak
You typically want to avoid naked pointers whenever possible, so the cleaner solution is what juanchopanza suggested and try to use std::vector.
The equivalent of Arrays.fill(list, 0); for a C++ vector looks like std::fill(list.begin(), list.end(), 0);
You can also simply declare a std::vector<short> list1(data.size()); to create it with zero initialized values or with a specific value std::vector<short> list1(data.size(), 0);

Using Struct Stat()

I'm trying to figure out how exactly to use stat() to capture information about a file. What I need is to be able to print several fields of information about a file. So..
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
int main() {
struct stat buf;
stat("file",&buf);
...
cout << st_dev << endl;
cout << st_ino << endl;
cout << st_mode << endl;
cout << st_nlink << endl;
cout << st_uid << endl;
cout << st_gid << endl;
cout << st_rdev << endl;
cout << st_size << endl;
cout << st_blksize << endl;
cout << st_blocks << endl;
cout << st_atime << endl;
cout << st_mtime << endl;
cout << st_ctime << endl;
...
}
I'm thoroughly confused about how to do this. Why is &buf a parameter to stat? I don't care about storing this information in memory, I just need the outputted fields within my c++ program. How do I access the information contained in the struct? Is buf actually supposed to contain the returned information from stat()?
Yes, buf is being used here as an out-parameter. The results are stored in buf and the return value of stat is an error code indicating if the stat operation succeeded or failed.
It is done this way because stat is a POSIX function, designed for C, which does not support out-of-band error reporting mechanisms like exceptions. If stat returned a struct, then it would have no way to indicate errors. Using this out-parameter method also allows the caller to choose where they want to store the results, but that's a secondary feature. It's perfectly fine to pass the address of a normal local variable, just like you have done here.
You access the fields of a struct like you would any other object. I presume you are at least familar with object notation? E.g. the st_dev field within the stat struct called buf is accessed by buf.st_dev. So:
cout << buf.st_dev << endl;
etc.
For another project, I've whipped up a little function that does something similiar to what you need. Take a look at sprintstatf.
Here's an example of usage:
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include "sprintstatf.h"
int
main(int argc, char *argv[])
{
char *outbuf = (char *)malloc(2048 * sizeof(char));
struct stat stbuf;
char *fmt = \
"st_atime (decimal) = \"%a\"\n"
"st_atime (string) = \"%A\"\n"
"st_ctime (decimal) = \"%c\"\n"
"st_ctime (string) = \"%C\"\n"
"st_gid (decimal) = \"%g\"\n"
"st_gid (string) = \"%G\"\n"
"st_ino = \"%i\"\n"
"st_mtime (decimal) = \"%m\"\n"
"st_mtime (string) = \"%M\"\n"
"st_nlink = \"%n\"\n"
"st_mode (octal) = \"%p\"\n"
"st_mode (string) = \"%P\"\n"
"st_size = \"%s\"\n"
"st_uid = \"%u\"\n"
"st_uid = \"%U\"\n";
lstat(argv[1], &stbuf);
sprintstatf(outbuf, fmt, &stbuf);
printf("%s", outbuf);
free(outbuf);
exit(EXIT_SUCCESS);
}
/* EOF */
This question may be way to old to comment but i am posting this as a reference
To get a good understanding about stat() function ,the reason for passing the stat reference and more importantly error handling are explained good in the below link
stat - get file status
You have several errors in your code:
You need &buf, with a single 'f'.
You need to say e.g. buf.st_dev when printing, since st_dev is a field in the struct variable.
Since buf is a local variable on the stack, you're not "saving the values to memory" permanently, it's just as long as that variable is in-scope.
This is how you return multiple values, typically, in C and C++. You pass a pointer to a structure, and the function being called fills in the structure with the values it has computed for you.
buf is the structure that stat loads with the information about the file you pass in the first parameter. You pass &buf here b/c you have buf allocated on the stack as a local variable and you must pass a pointer to the stat function to enable it to load the data.
All variables of st_* are part of the struct stat object and thus must be accessed via your local buf variable as buf.st_uid, etc.
Similar thing is with ctime library. Is designed similar way.
First is to create empty struct.
You have access to object of the struct, but all fields are empty.
Then You use that function (&name-of-created-obiect) and is an adrres to point obiect outside of that function.
Function is designed to store all info to that struct obiect from given reference, and kaboom, you have obiect with ready data to use.
Otherwise, if You don't want use pointer, then you must use
Obiect = function(null);
With pointer
Function(&obiect);