I am attempting to recreate some "R" scripts in C++, just for the fun of it. Have used C decades ago but not recently. Now what I have is a bit of code where I am reading data from a binary file and placing the data into a structure (or class) with an unknown number of array structures (for the file reading side). Not knowing exactly how many arrays are needed, I define the number after reading another binary file which contains that data. So, I have two options; one to enter new data (which saves that plus the number of arrays to two files); another to read saved data back in (which provides the number of needed array structures). Having done either option via 'IF' conditionals, I need the new or recovered data to perform math on outside those conditionals. This is where things go wrong. The data is not available. The simple example recreates the problem and I have not stumbled upon the solution yet. I am not familiar enough with C++ to find what is most likely something simple to fix. The 'closed' function's first line outside the 'if' conditionals does work as expected, but that's not the data I need, and I don't want that line in the program.
#include <iostream>
using namespace std;
void closed(void);
class traverse {
public:
int sta;
};
int main()
{
closed();
return 0;
}
void closed(void)
{
traverse stations[1]; // removes 'stations was not declared' error on line 35.
cout << "Enter 1 or 2\nSelect: ";
int selType;
cin >> selType;
if (selType == 2) {
cout << selType << " selected\n";
traverse stations[1];
stations[0].sta = 2; //need this member value available outside conditional.
cout << "Value is " << stations[0].sta << " inside." << endl;
} else {
cout << selType << " selected\n";
traverse stations[1];
stations[0].sta = 1; //need this member value available outside conditional.
cout << "Value is " << stations[0].sta << " inside." << endl;
}
cout << "Value is " << stations[0].sta << " outside." << endl;
}
I originally used a 'struct' but decided to try a 'class' to discover the differences. But, the same problem persists with both, so I don't think it is anything with the definitions, but perhaps with different declarations. Any ideas would be greatly appreciated. Thanks.
If you need it to live longer than the scope of the if, then declare it in the outer scope where you need it to continue living.
After you added this line to deal with the warning:
traverse stations[1]; // removes 'stations was not declared' error on line 35.
You left the declaration of stations inside the if. That hides the outer name, and will receive the data, then go out of scope when the brace-enclosed block exits. To put data into the outer stations don't hide it.
If you need this data to live longer than the function call itself, you'll need to pass in an object to be written into, or allocate and return one to the caller. Perhaps a vector? I don't like (or recommend) to pass raw arrays because they decay to pointers and lose the bounds encoding from their type. That makes it too easy to go out of bounds without being very careful. There are smart pointer wrappers you could use, or a span class, etc., to help do it more sensibly.
Related
Hello all c++ noob here,
For my homework in c++ I must create a program that inputs 5 cities and prints them in order and reverse order by the users choice using arrays and seperate functions. The homework requires that you use all these functions to operate. The program runs fine until I enter o or r for reverse order. I get a segmentation error. I think I am printing or passing the strings incorrectly.
Here is my declaration of my array function
void displayInOrder (string o[5]);
Now here is my function with the executable code.
void displayInOrder (string o[5])
{
cout << "Here are the cities in order: " << endl;
cout << o[0] << " " << o[1] << " " << o[2] << " " << o[3] << " " << o[4]
<< endl; //the error seems to lie somewhere in here and the same
//in the reverse function
}
Now in the main I am calling the function like this.
displayInOrder (&cities[5]);
I think I am either calling the function incorrectly, declaring it wrong, or printing it wrong. It's been a while since I programmed in C++ and I am a bit of a noob. I appreciate any help anyone has to offer.
The displayInOrder() function is expecting a pointer to an the whole array. Instead, you passed a pointer to cities[5]. This has two problems:
It's a pointer to a specific element, not the whole array.
The last element of the array is cities[4], so you're accessing outside the array bounds.
You should call the function this way:
displayInOrder(cities);
There's no need to use &, an array variable automatically decays to a pointer when used as a function argument.
I'm reading Inside The C++ Object Model and find confused about inline function expansion.
In general, each local variable within the inline function must be introduced into the enclosing block of the call
as a uniquely named variable. If the inline function is expanded multiple times within one expression, each
expansion is likely to require its own set of the local variables. If the inline function is expanded multiple
times in discrete statements, however, a single set of the local variables can probably be reused across the
multiple expansions.
Here, what does it mean to expand inline function multiple times in discrete statements and how could that happen? Can anyone raise a concrete example to apply this?
I had some trouble to handle the term discrete statement (especially because it has been emphasized multiple times). I tried to find something like a clear definition (by google) but I couldn't. Thus, I decided to read this literally as one statement (with discrete in the sense of separate).
Denoting a function inline is just a hint to the compiler that the programmer would like to have the function body inserted directly at every "call point" (instead of simply calling the function). Actually, the compiler decides whether the function is really inlined. (It might be even inlined at one point of call but become a function call at another point.) If a macro is used instead of the inline function, the inline requirement would be granted (as macro expansion is actually nothing else than text replacement). Of course, macros have a lot of limitations which inline functions have not. One of them is that inline functions may have local variables.
I made a synthetic example. It's not code "ready for production" but it hopefully helps to illustrate the topic:
#include <iostream>
using namespace std;
inline int absValue(int a)
{
int mB = -a;
return a < 0 ? mB : a;
}
int main()
{
int value;
// use input to prevent compile-time computation
cout << "input: " << flush;
cin >> value;
// multiple usages of absValue()
cout << "value: " << value << endl
<< "absValue(value): "
<< absValue(value)
<< endl
<< "absValue(-value): "
<< absValue(-value)
<< endl;
// done
return 0;
}
The second output statement calls function absValue() multiple times where the call should be inlined. I imagine it like:
// multiple usages of absValue()
cout << "value: " << value << endl
<< "absValue(value): "
<< {
int mB = -(value);
return (value) < 0 ? mB : (value);
}
<< endl
<< "absValue(-value): "
<< {
int mB = -(-value);
return (-value) < 0 ? mB : (-value);
}
<< endl;
There are two occurrences of mB in this statement. On one hand, these are two separate local variables. On the other hand, they may share the same storage on stack as they are used consecutively. (They might not share the same storage if the compiler optimization introduces some kind of code re-ordering which results in interleaving of the first and second expansion of absValue().)
This whole explanation is rather theoretically. Practically, the compiler will hopefully put mB into a register or even optimize most of the code away.
I fiddled a little bit with godbolt to illustrate it further. Finally, I must admit that it proofs essentially my last paragraph above.
I had to write a program that declares char text[16]; and int number; and then fills it with input from the user. Then I have to call another function (without passing anything) and recall that data from the stack and display it.
I was able to find both of them
// This is the function that is called without passing any variables
int number;
char text[16];
cout << *(&text + 5) << endl; // This outputs the correct text but I can not figure out how to assign it to text
number = *(int*)(&number + 20); // This works and outputs the correct number and saves correctly to int number;
cout << "\tnumber: "
<< number
<< endl;
cout << "\ttext: "
<< text
<< endl;
I would like to know if there is a way to transfer the text from *(&text + 5) to char text[16];
What you are doing is going to result in undefined behavior. Depending heavily on the compiler and therefore in turn on the architecture. The proof being that when I compile and run your code with different optimization flags I get different results. Check out https://en.wikipedia.org/wiki/Buffer_overflow
The first expression *(&text + 5) evaluates to taking the address of the text pointer in memory, adding 5 to it and then dereferencing that to get a character value that is stored at that location. This can be pretty much anything on the stack at that time.
&number + 20 will definitely go off the "visible" stack, this is pointer arithmetic and will result in you adding 20*sizeof(int) to the pointer to the memory address of number on the stack.
If this is what you are intending to do then you should probably use strcpy as suggested by #JafferWilson
From reading the comments on the answer by Curious the answer is:
There is no proper way to read local variables in another function in C++ without passing them (or pointers to them or references to them) as parameters (or within objects you pass as parameters).
You can assign file scope (so called global) variables and read them in other functions. That is almost always a bad idea.
I get the feeling you might be coming from an assembler programming background to even try this sort of thing. You need to surrender a bit more to the structured programming paradigm.
I was writing a simple program to test how the scope of variables works, but I'm obtaining unexpected results, so I was hoping you could give me an hand to understand them.
I compiled this code
#include<iostream>
using namespace std;
void myFunction1()
{
int e;
cout << e << endl;
e++;
cout << e << endl<<endl;
}
int main()
{
cout << "MAIN" << endl;
int a,b,c,d;
cout << "a= " << a << endl;
cout << "b= " << b << endl;
cout << "c= " << c << endl;
cout << "d= " << d << endl<<endl;
cout << "MY_FUNC" << endl;
myFunction1();
myFunction1();
myFunction1();
}
and obtained this output
MAIN
a= -1617852976
b= 32767
c= 0
d= 0
MY_FUNC
32675
32676
32676
32677
32677
32678
So, there are two things I really don't understand
1) In the main() function I'm creating 4 int variables (a,b,c,d) WITHOUT initializing them, so I expect them to assume a different value each time I run the code. Strange thing is, the first variable (a) is always different, while the others always assume the same values (b=32767, c=d=0)
2) The function output is even stranger to me.
Again, I'm creating a variable e without initializing it, so the first time it assumes a random value (in the example, e=32675).....then, I increase it by one, so that it prints 32675 and 32676, and that sounds right.
But how come the second time I call the function, e keeps the previous value (32676)? I thought e was created each time I call myFunction1() and deleted at the end of the function, so that e assumed a different random value each time (since I don't initialize it). Why is the value of e stored even if the variable goes out of scope?
Uninitialized primitive values are simply not defined. They can have any value.
It is an undefined behavior. That's why it doesn't make any sense to analyze the behavior of this program.
In the main() function I'm creating 4 int variables (a,b,c,d) WITHOUT initializing them, so I expect them to assume a different value each time I run the code
This assumption is flawed. They may have a different value each time you run the code, but they may not. Anything could happen. The point of UB is that you should drop all your assumptions.
But how come the second time I call the function, e keeps the previous value (32676)? I thought e was created each time I call myFunction1() and deleted at the end of the function, so that e assumed a different random value each time (since I don't initialize it)
It does. If you replace "random" for the more correct "arbitrary", then the results you're seeing fit that pattern just fine.
It's just pure luck, and comes down to the state you're leaving unclaimed memory in at each stage of your program's execution.
A good way to help you understand this is to explain in terms of memory allocation.
When you run a program, a certain amount of memory that is not used is assigned to your variable.
Computers are lazy, the best way to delete a data is to forget where it is stored. When you assign a chunk of memory to a variable, you are telling the computer to remember where that certain data belongs to.
If it so happens that it was used prior to you assigning the memory to the variable, it will simply read (let's say 4 bytes for a common machine) and get the data from that location.
Hope that this helps =)
I am working on a small console game on my free time and have come across a bug I can't seem to fix no matter what I try. I have tried a lot of different things with the pointers so this is just the latest version of my code. I have been searching around and a few questions other's have asked indicated I may be experiencing a memory leak, or that I am reading values from beyond my arrays (don't understand how). However, those questions have been solved without leaving me any hints as to what is wrong with my code.
Basically, I have a function called int * spendAttribute(int point);
Since anything created in that function is out of scope in my main() I want to take 6 int out of that function, and bring them into my main().
I thought "hey why not use a pointer!" The function is supposed to return a pointer to an array created during the function, and paste it to another pointer created in main(), this has worked once before in my main(), but now it's not working and I have no clue why.
int * spendAttribute(int point)
{
string choice;
int hp,hpT,endur,endurT,dmg,dmgT,armor,armorT,agility,agilityT,evade,evadeT;
while(condition)
{
//do a bunch of junk ....
}
int stats[6] = {hp,endur,dmg,armor,agility,evade};
//some cout testing to see if values are correct (they are)
int* p_stats = new int [6]; //create a block of 6
p_stats = &stats[0]; //point to the first value of stats array
return p_stats; //return pointer
delete [] p_stats; //delete blocks
}
Note: I have tried without deleting the blocks and it still does not work. I tried this since I read that it might be a memory leak.I have tried it without using new at all.
main()
{
//.... some junk
while(main game loop)
{
int * pointer;
cout << "*************** Enter 'begin' to commence ****************** " << endl ;
cout << "*************** Enter 'spend' to use new attribute points ** " << endl ;
cin >> beginChoice; //declared before while loop
if(beginChoice == "spend")
{
cout << "total attributes: " << Bryan.returnAttribute() << endl ;
pointer = spendAttribute(Bryan.returnAttribute()); //copy pointer
cout << "TEST: " << endl ;
cout << pointer[0] << endl ; //out put is a bunch of random numbers..
cout << pointer[1] << endl ;
cout << pointer[2] << endl ;
cout << pointer[3] << endl ;
cout << pointer[4] << endl ;
cout << pointer[5] << endl ; //SOME DAMN BUG HERE
Bryan.addMaxHp(pointer[0]);
Bryan.addEndurance(pointer[0]);
Bryan.addDmg(pointer[0]);
Bryan.addArmor(pointer[0]);
Bryan.addAgility(pointer[0]);
Bryan.addEvasion(pointer[0]);
//after this character ends up having some ridiculous stats like -564553535%
//evasion or 9879967856 armor...
}
}
}
This method of transferring the array over to main worked for me before in this exact file, so I don't know exactly how I am getting these errors or what's causing them. I have even tried deleting the previous pointer used to see if thats what was causing it but it wasn't.
Please Halp.
Because you return a pointer to a local variable, and when that local variable goes out of scope you have a stray pointer.
And no, your allocation doesn't help, as you reassign the pointer to point to the local array, instead of copying into the allocated area. This of course means you also have a memory leak.
Regarding memory leak, you will still have a memory leak even when you fix the above problem. The reason being that you return from the function before you delete[] the pointer, and return returns from the function immediately, all code after a return statement is dead code. That means every time you call the function, it will allocate new memory which will never be free'd.
There are two obvious solutions to both the problems above: One is to allocate memory, copy the array into the allocated memory, and returning the pointer, and in the caller you do delete[] on the pointer.
The second solution is to pass in an array as argument, and use that instead of the local stats array.
p_stats is a pointer to int.
First you assign it to a newly allocated place in memory.
Then you move the pointer to point to local storage and return that. My guess is that you really wanted to return stats. Your options are:
Returns std::vector< int >. Probably simplest.
Modify your function to take a buffer to data and a length and fill it in.
Return std::array if available and you know it will be a fixed size of 6.
Although you could copy the data into p_stats then return that, it is not ideal because the calling function is then responsible to delete the data later.
If the fields have different meanings, you might want to create a struct with meaningful names for the values, and get your function to return that struct. e.g.
struct SpendAttribute // in header
{
int hp;
int endur;
int dmg;
int armor;
int agility:
int evade
};
SpendAttribute spendAttribute( int point )
{
SpendAttribute res;
// enter code here
return res;
}
There is a final option of putting the data into a smart-pointer like boost::shared_array<int> or you can use shared_ptr with an array-deleter.
For now, just return std::vector<int>