C++ got wrong value from array of struct - c++

The problem is as described above. When I try to read values from loaded *.so file (using libdl), whih are in struct I am getting wrong values
Code of application:
#include <dlfcn.h>
#include <iostream>
/* For face data type reproduction */
#define GET_FACE_XYZ_SIZE 1
/* For face_array reproduction */
#define GET_FACE_ARRAY_SIZE 2
#define GET_OBJECT_DATA 3
typedef struct face {
float x[1000];
float y[1000];
float z[1000];
int vertices;
} face;
int main()
{
void *hook;
int (*fn)(int request_type, void *ptr);
hook = dlopen("/root/osms/dlopen-test/lib.so", RTLD_LAZY);
if(!hook)
{
std::cout << "Couldn't find lib.so" << std::endl;
}
fn = dlsym(hook, "object_info");
int face_array_size = fn(GET_FACE_ARRAY_SIZE, NULL);
std::cout << "FACE_ARRAY_SIZE: " << face_array_size << std::endl;
face pointer[face_array_size];
fn(NULL, pointer);
dlclose(hook);
std::cout << "pointer[0].z[1]: " << pointer[0].z[1] << std::endl;
return 0;
}
and code of lib.so:
/* For face data type reproduction */
#define GET_FACE_XYZ_SIZE 1
/* For face array reproduction */
#define GET_FACE_ARRAY_SIZE 2
#define GET_OBJECT_DATA 3
typedef struct face {
float x[1000];
float y[1000];
float z[1000];
int vertices;
} face;
extern "C" int object_info(int request, void *ptr)
{
face face_array[2];
face_array[0].x[0] = 1.1;
face_array[0].y[0] = 0.5;
face_array[0].z[0] = 1.2;
face_array[0].x[1] = 1.6;
face_array[0].y[1] = -0.11;
face_array[0].z[1] = -12;
face_array[0].x[2] = -0.12;
face_array[0].y[2] = 0.24;
face_array[0].z[2] = -0.12;
face_array[0].vertices = 3;
face_array[1].x[0] = -1.1;
face_array[1].y[0] = 0.15;
face_array[1].z[0] = -1.2;
face_array[1].x[1] = -1.6;
face_array[1].y[1] = 0.11;
face_array[1].z[1] = 1.2;
face_array[1].x[2] = 0.12;
face_array[1].y[2] = -0.24;
face_array[1].z[2] = 0.12;
face_array[1].vertices = 3;
if(request == GET_FACE_ARRAY_SIZE)
{
return 2;
}
else
{
ptr = face_array;
}
}
The expected output is pointer[0].z[1]: -12 but I am getting pointer[0].z[1]: -0.12. What's wrong in my code ?
Thanks in advance

Accessing
pointer[0].z[1]
Has undefined behaviour, because it has an indeterminate value.
object_info never modifies the array pointed by ptr. It simply modifies a local array, and assigns the local ptr to point to that local array.
A solution: Don't declare a local array, and instead modify the array pointed by the argument. In other words, repace face face_array[2]; with:
face* face_array = (face*)ptr;
And get rid of the ptr = face_array; that does nothing meaningful.
object_info is declared to return int, but not all code paths return a value. When the function reaches the end of object_info without a return statement, the behaviour is undefined.
A solution: Always return a value if the function is not void.
face_array_size is not a compile time constant value, so face pointer[face_array_size]; will declare a variable length array. VLA are not allowed in C++.
Either use C (VLA are supported since C99, but only optionally supported since C11) instead or use a dynamic array: std::vector<face> or make peace with the fact that your program is not standard compliant.

The variable "face_array" in function object_info and the variable "pointer" in main are not the same variable.
The statement "ptr = face_array" does not change the content of "pointer".
extern "C" int object_info(int request, face *face_array)
{
if(request == GET_FACE_ARRAY_SIZE)
return 2;
face_array[0].x[0] = 1.1;
face_array[0].y[0] = 0.5;
face_array[0].z[0] = 1.2;
face_array[0].x[1] = 1.6;
face_array[0].y[1] = -0.11;
face_array[0].z[1] = -12;
face_array[0].x[2] = -0.12;
face_array[0].y[2] = 0.24;
face_array[0].z[2] = -0.12;
face_array[0].vertices = 3;
face_array[1].x[0] = -1.1;
face_array[1].y[0] = 0.15;
face_array[1].z[0] = -1.2;
face_array[1].x[1] = -1.6;
face_array[1].y[1] = 0.11;
face_array[1].z[1] = 1.2;
face_array[1].x[2] = 0.12;
face_array[1].y[2] = -0.24;
face_array[1].z[2] = 0.12;
face_array[1].vertices = 3;
}

Related

A pointer to const int in c++

In c++ I have the next code
int main() {
int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = &i;
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 12"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
Now the same code with constant integer i
int main() {
const int i = 1;
cout<<"i = "<<i<<endl; //prints "i = 1"
int *iPtr = (int*)&i; //here I am usint a type conversion
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 1"
(*iPtr) = 12; //changing value through pointer
cout<<"i = "<<i<<endl; //prints "i = 1"
cout<<"*iPtr = "<<*iPtr<<endl; //prints "*iPtr = 12"
system("pause");
return 0;
}
As you can see, in second case with constant integer, there are two different values for *iPtr and const i, but the pointer *iPtr shows to constant i.
Please tell me what happens in the second case and why?
Your second code has undefined behavior. You can't change const data via a pointer-to-non-const. You are lucky your code didn't simply crash outright when trying to modify a read-only value.
In any case, the result you are seeing is because the compiler knows that i is const and has a value that is known at compile time. So the compiler is able to optimize away i in the cout statement and use 1 directly instead. That is why you see 1 when printing i and see 12 when printing *iPtr.
You are trying to remove the const qualifier of your variable.
In C++, you should use const_cast to do that.
However, const_cast can only be used in some precise circomstances: constness should only be removed from pointers/references to data which have been declared non-const at top level, otherwise the compiler may optimize the variable and modifying it through the pointer/reference would result in undefined behaviour.
For example, this is not legal :
const int i = 1;
const int *iPtr = &i;
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Invalid : i is first declared const !!
But this is totally legal :
void modifyConstIntPtr(const int *iPtr) {
int *iSuperPtr = const_cast<int*>(iPtr);
*iSuperPtr = 2; // Valid : i is first declared non-const !!
}
void modifyConstIntRef(const int &iRef) {
int &iSuperRef = const_cast<int&>(iRef);
iSuperRef = 3; // Valid : i is first declared non-const !!
}
int main() {
int i = 1;
modifyConstIntPtr(&i);
std::cout << i << std::endl;
modifyConstIntRef(i);
std::cout << i << std::endl;
}
This aspect of C++ is well detailed here: https://stackoverflow.com/a/357607/3412316)

Attempt to create a structure object creating an Access Violation Writing Error In Location 0x3FE00000

I'm learning to use structures and making a text-based RPG, and I'm aware that items should be a class in my code, however, since I am using structures and I'm new to c++ and programming I do not understand what exactly has gone wrong with my code nor how to fix it, the error occurs where I try to create a structure object called player. (I would also like to apologize for my messy code, i'm messing around and will be cleaning it once I get what I have working.)
This is my first attempt, I haven't tried much because I'm unsure what exactly to try.
#include "pch.h"
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct item {
double resistance, attack;
string name;
};
item none, WoodenBoots, LeatherChestplate, WoodenShield, WoodenClub, WoodenSword;
struct mobs {
int health, attack;
double droprate, resistance;
item drops[3];
};
item GetData(string object);
int main()
{
none.attack = 0;
none.resistance = 0;
none.name = "none";
WoodenBoots.resistance = .05;
WoodenBoots.attack = 0;
WoodenBoots.name = "Wooden Boots";
LeatherChestplate.resistance = .2;
LeatherChestplate.attack = 0;
LeatherChestplate.name = "Leather Chestplate";
WoodenShield.resistance = .1;
WoodenShield.attack = 0;
WoodenShield.name = "Wooden shield";
WoodenClub.resistance = 0;
WoodenClub.attack = 1.2;
WoodenClub.name = "Wooden Club";
WoodenSword.resistance = .05;
WoodenSword.attack = 1.5;
WoodenSword.name = "Wooden Sword";
mobs goblin;
goblin.attack = 1;
goblin.health = 10;
goblin.droprate = .5;
goblin.resistance = .1;
goblin.drops[1] = WoodenClub;
goblin.drops[2] = WoodenShield;
goblin.drops[3] = WoodenBoots;
mobs Alpha_Goblin;
Alpha_Goblin.attack = 2;
Alpha_Goblin.health = 15;
Alpha_Goblin.droprate = .5;
Alpha_Goblin.resistance = .1;
Alpha_Goblin.drops[1] = WoodenSword;
Alpha_Goblin.drops[2] = WoodenShield;
Alpha_Goblin.drops[3] = LeatherChestplate;
struct pdata {
item Playeritem[6];
item PlayerWeapon;
}player;
player.PlayerWeapon = WoodenSword;
cout << player.PlayerWeapon.name << endl;
player.PlayerWeapon = GetData("weapon");
player.Playeritem[0] = GetData("sheild");
player.Playeritem[1] = GetData("head");
player.Playeritem[2] = GetData("torso");
player.Playeritem[3] = GetData("legs");
player.Playeritem[4] = GetData("feet");
player.Playeritem[5] = GetData("hands");
string weapon = player.PlayerWeapon.name;
cout << weapon << endl;
system("pause");
}
I expect it to create the structure and to move on to defining the item values inside the struct. i get the following error on the last line of the struct pdata: Exception thrown at 0x57115139 (vcruntime140d.dll) in Structure.exe: 0xC0000005: Access violation writing location 0x3FE00000.
In C++ arrays are indexed from zero to num_elements - 1
So if you declare
int myArray[3];
and then try to access:
myArray[3] = 5;
You are going to get undefined behavior that may manifest itself as an access violation depending on your compiler and debug settings.
In Visual Studio you can use the Exception Settings and check off access violation exceptions while running in debug, and have the execution halt before it is thrown.

How to declare child pointer with parent from different structs in C++

I want to connect child on line no->rodzic = tz; to pointer tz which points to "parent", but those are 2 different structs. Is it possible to do like I think? My ERROR is: cannot convert... etc in assignment
struct lotwarta {
int wartosc,x,y;
lotwarta *parent;
};
struct lzamknieta {
int wartosc,x,y;
lzamknieta *parent;
lzamknieta *tz;
};
lzamknieta *nz;
nz = new lzamknieta; // do listy zamknietej dodajemy 1 element
nz->wartosc = 0;
nz->x = startx;
nz->y = starty;
nz->parent = NULL;
lzamknieta* tz = nz;
lotwarta *no;
no = new lotwarta;
no->wartosc = 0;
no->x = startx;
no->y = starty;
no->parent = NULL;
cout << no->rodzic << endl;
lotwarta *to = no;
if( (y!=1) && (G[y-1][x]!=5) )
{
no = new lotwarta;
no->wartosc = euklides(x,y-1);
no->x = x;
no->y = y-1;
no->parent = tz; <- here I have this error
}
I don't really know what this code should do,
but you can assign a pointer of a type to another type by simply casting its value:
no->rodzic = reinterpret_cast<lzamknieta*>(tz); //in this case tz would be casted to a pointer of type lzamknieta
But it is not always a good idea, to cast a pointer to another type, it depends on the context.

Arduino addition assignment

I do some programming using Arduino, but I have a problem. In the loop() function I want to add a value to a variable, pwm, each time the loop() function is executed. I obtain that value from some function I wrote and add it to pwm with the command pwm += result, but it does not work. If I print pwm, I always get zero. Even though printing result gives me some non-zero value. The whole code is:
float pwm = 0;
float result = 0;
void loop(){
....
errV = w - cm;
errDtV = errOldV - errV;
result = flc->cog(errV, errDtV);
Serial.print("RESULT: ");
Serial.println(result);
pwm += result;
Serial.println(pwm);
}
And the output is like this:
RESULT: 31.98
0.00
What might be wrong?
EDIT: Here is the whole sketch
#include "FSet.h"
#include "FRule.h"
#include "Flc.h"
#include <NewPing.h>
#include "MotorControl.h"
MotorControl* m;
Flc* flc;
FRule* rule1,*rule2,*rule3,*rule4,*rule5,*rule6,*rule7,*rule8,*rule9;
NewPing sonar1(32,33,200);
static int dirA = 9;
static int pwmA = 8;
// Setup the FSets
FSet errZ(0,5,0);
FSet errMP(-15,15,0);
FSet errLP(-30,15,-1);
FSet errDtLN(-4,2,-1);
FSet errDtMN(-2,2,0);
FSet errDtZ(0,2,0);
FSet errDtMP(2,2,0);
FSet errDtLP(4,2,1);
FSet cntLN(-40,20,0);
FSet cntMN(-20,20,0);
FSet cntZ(0,20,0);
FSet cntMP(20,20,0);
FSet cntLP(40,20,0);
void setup(){
Serial.begin(4800);
pinMode(dirA,INPUT);
//Creating FRules for test
rule1 = new FRule(&errZ,&errDtMP,&cntMN);
rule2 = new FRule(&errZ,&errDtZ,&cntZ);
rule3 = new FRule(&errZ,&errDtMN,&cntMP);
rule4 = new FRule(&errMP,&errDtLP,&cntMN);
rule5 = new FRule(&errMP,&errDtMN,&cntMP);
rule6 = new FRule(&errLP,&errDtMP,&cntMP);
rule7 = new FRule(&errLP,&errDtZ,&cntLP);
rule8 = new FRule(&errLP,&errDtMN,&cntLP);
rule9 = new FRule(&errLP,&errDtLN,&cntLP);
flc = new Flc(9);
flc->addRule(rule1);
flc->addRule(rule2);
flc->addRule(rule3);
flc->addRule(rule4);
flc->addRule(rule5);
flc->addRule(rule6);
flc->addRule(rule7);
flc->addRule(rule8);
flc->addRule(rule9);
}
int errV = 0;
int errOldV = 0;
int errDtV = 0;
int w = 30;
unsigned int uS;
unsigned int cm;
float pwm1 = 0;
float result = 0;
void loop(){
uS = sonar1.ping();
cm = (uS / US_ROUNDTRIP_CM);
errV = w - cm;
errDtV = errOldV - errV;
result = flc->cog(errV,errDtV);
Serial.print("RESULT: ");
Serial.println(result);
pwm1 = pwm1 + result;
Serial.println(pwm1);
analogWrite(pwmA,pwm1);
errOldV = errV;
}
FLC class header file:
#ifndef FLC_H
#define FLC_H
#include "Arduino.h"
#include "FRule.h"
class Flc {
public:
Flc(int size);
~Flc();
int addRule(FRule* rule);
int mom(float x1,float x2);
float cog(float x1,float x2);
FRule** rules;
private:
int last;
int size;
float h;
float numerator = 0;
float denominator = 0;
float result = 0;
};
#endif
FLC class source:
#include "Arduino.h"
#include "Flc.h"
Flc::Flc(int size){
this->rules = (FRule**) malloc(sizeof(FRule*) * size);
this->size = size;
last = -1;
}
Flc::~Flc(){
free(rules);
}
int Flc::addRule(FRule* rule){
this->rules[++last] = rule;
return last;
}
int Flc::mom(float x1,float x2){
return 0.0;a
}
float Flc::cog(float x1, float x2){
for(int i = 0; i < size;i++){
h = rules[i]->dof(x1,x2);
float area = rules[i]->widthOfCon() * ( h - h*h/2);
numerator += rules[i]->cntrOfCon() * area;
denominator += area;
}
result = numerator / denominator;
return result;
}
Something in your function cog() is stomping on the variable pwm. Once the float variable is corrupt, Serial.print() will just show zero. The sample below shows that with the float set to 0xffffff, the floating point math library stops making any operation on the variable.
Run the sample program below and you will see that one time pwm prints correctly. After the first bad call, it prints zeros. Also the memory occupied no longer changes.
pwm=0.50 zpwm=0.50
pwm=0.00 zpwm=3.95 result=3.45
255-255-255-255
pwm=0.00 zpwm=4.45
pwm=0.00 zpwm=7.90 result=3.45
255-255-255-255
Sample program showing a function that writes to wrong memory location.
Looking at the memory map output by the linker, the variables are placed in memory in the order listed. So writing past the end of var, will corrupt pwm.
float zpwm = 0;
byte var = 0;
float pwm = 0;
float result = 0;
float badactor() {
*((long*)(&var+1)) = -1;
return 3.45;
}
void setup() {
Serial.begin(57600);
}
void loop() {
zpwm += 0.5;
pwm += 0.5;
Serial.print("pwm=");
Serial.print(pwm);
Serial.print(" zpwm=");
Serial.println(zpwm);
result = badactor();
pwm += result;
zpwm += result;
Serial.print("pwm=");
Serial.print(pwm);
Serial.print(" zpwm=");
Serial.print(zpwm);
Serial.print(" result=");
Serial.println(result);
uint8_t* ptr;
ptr = (uint8_t*)&pwm;
Serial.print((int)*(ptr));
Serial.print("-");
Serial.print((int)*(ptr+1));
Serial.print("-");
Serial.print((int)*(ptr+2));
Serial.print("-");
Serial.println((int)*(ptr+3));
delay(1000);
}

How can I return a value from a function

I used a function to calculate information about certain instructions I intialized in a map,like this
void get_objectcode(char*&token1,const int &y)
{
map<string,int> operations;
operations["ADD"] = 18;
operations["AND"] = 40;
operations["COMP"] = 28;
operations["DIV"] = 24;
operations["J"] = 0X3c;
operations["JEQ"] =30;
operations["JGT"] =34;
operations["JLT"] =38;
operations["JSUB"] =48;
operations["LDA"] =00;
operations["LDCH"] =50;
operations["LDL"] =55;
operations["LDX"] =04;
operations["MUL"] =20;
operations["OR"] =44;
operations["RD"] =0xd8;
operations["RSUB"] =0x4c;
operations["STA"] =0x0c;
operations["STCH"] =54;
operations["STL"] =14;
operations["STSW"] =0xe8;
operations["STX"] =10;
operations["SUB"] =0x1c;
operations["TD"] =0xe0;
operations["TIX"] =0x2c;
operations["WD"] =0xdc;
if ((operations.find("ADD")->first==token1)||(operations.find("AND")->first==token1)||(operations.find("COMP")->first==token1)
||(operations.find("DIV")->first==token1)||(operations.find("J")->first==token1)||(operations.find("JEQ")->first==token1)
||(operations.find("JGT")->first==token1)||(operations.find("JLT")->first==token1)||(operations.find("JSUB")->first==token1)
||(operations.find("LDA")->first==token1)||(operations.find("LDCH")->first==token1)||(operations.find("LDL")->first==token1)
||(operations.find("LDX")->first==token1)||(operations.find("MUL")->first==token1)||(operations.find("OR")->first==token1)
||(operations.find("RD")->first==token1)||(operations.find("RSUB")->first==token1)||(operations.find("STA")->first==token1)||(operations.find("STCH")->first==token1)||(operations.find("STCH")->first==token1)||(operations.find("STL")->first==token1)
||(operations.find("STSW")->first==token1)||(operations.find("STX")->first==token1)||(operations.find("SUB")->first==token1)
||(operations.find("TD")->first==token1)||(operations.find("TIX")->first==token1)||(operations.find("WD")->first==token1))
{
int y=operations.find(token1)->second;
//cout<<hex<<y<<endl;
}
return ;
}
which if I cout y in the function gives me an answer just fine which is what i need
but there is a problem tring to return the value from the function so that I could use it outside the function , it gives a whole different answer, what is the problem
Yours second argument in the function is a constant reference. Try replacing -
void get_objectcode(char*&token1,const int &y)
with
void get_objectcode(char*&token1,int &y)
and in your if condition, remove the new declaration of y and replace it with -
y=operations.find(token1)->second;
Hope this helps !
This is probably closer to what you want:
void get_objectcode(const char *token, int &y)
{
typedef std::map<std::string,int> OpMap;
OpMap operations;
operations["ADD" ] = 18;
operations["AND" ] = 40;
operations["COMP"] = 28;
operations["DIV" ] = 24;
// etc.
operations["SUB" ] = 0x1c;
operations["TD" ] = 0xe0;
operations["TIX" ] = 0x2c;
operations["WD" ] = 0xdc;
OpMap::iterator result = operations.find(token);
// note: assigns 0 to y if token is not found
y = (result == operations.end()) ? 0 : result->second;
//std::cout << std::hex << y << std::endl;
}
Take a look at boost assign map_list_of here. It can be used to assign map. Then use find method from the map (the reference is here)
Your map exists only within that function. Therefore, the elements only exist within that function. If, at the place where you call the function, you're initialising a reference with y, then that will be a reference to an element that will cease to exist.
You should not really be creating the map every time the function is called, and at least it would be preferable to just return the value normally from the function:
std::map<std::string,int> operations;
operations["ADD"] = 18;
operations["AND"] = 40;
operations["COMP"] = 28;
operations["DIV"] = 24;
operations["J"] = 0X3c;
operations["JEQ"] = 30;
operations["JGT"] = 34;
operations["JLT"] = 38;
operations["JSUB"] = 48;
operations["LDA"] = 00;
operations["LDCH"] = 50;
operations["LDL"] = 55;
operations["LDX"] = 04;
operations["MUL"] = 20;
operations["OR"] = 44;
operations["RD"] = 0xd8;
operations["RSUB"] = 0x4c;
operations["STA"] = 0x0c;
operations["STCH"] = 54;
operations["STL"] = 14;
operations["STSW"] = 0xe8;
operations["STX"] = 10;
operations["SUB"] = 0x1c;
operations["TD"] = 0xe0;
operations["TIX"] = 0x2c;
operations["WD"] = 0xdc;
int get_objectcode(const std::string& key)
{
std::map<std::string, int>::iterator it = operations.find(key);
if (it == operations.end())
return -1;
else
return it->second;
}