Given a program of :
int main()
{
short myVariableName1; // stores from -32768 to +32767
short int myVariableName2; // stores from -32768 to +32767
signed short myVariableName3; // stores from -32768 to +32767
signed short int myVariableName4; // stores from -32768 to +32767
unsigned short myVariableName5; // stores from 0 to +65535
unsigned short int myVariableName6; // stores from 0 to +65535
int myVariableName7; // stores from -32768 to +32767
signed int myVariableName8; // stores from -32768 to +32767
unsigned int myVariableName9; // stores from 0 to +65535
long myVariableName10; // stores from -2147483648 to +2147483647
long int myVariableName11; // stores from -2147483648 to +2147483647
signed long myVariableName12; // stores from -2147483648 to +2147483647
signed long int myVariableName13; // stores from -2147483648 to +2147483647
unsigned long myVariableName14; // stores from 0 to +4294967295
unsigned long int myVariableName15; // stores from 0 to +4294967295
cout << "Hello World!" << endl;
cout << myVariableName1 << endl;
cout << myVariableName2 << endl;
cout << myVariableName3 << endl;
cout << myVariableName4 << endl;
cout << myVariableName5 << endl;
cout << myVariableName6 << endl;
cout << myVariableName7 << endl;
cout << myVariableName8 << endl;
cout << myVariableName9 << endl;
cout << myVariableName10 << endl;
cout << myVariableName11 << endl;
cout << myVariableName12 << endl;
cout << myVariableName13 << endl;
cout << myVariableName14 << endl;
cout << myVariableName15 << endl;
cin.get();
return 0;
}
Printing out the unassigned variables will print whatever was stored in that memory location previously. What I've noticed is that across multiple consecutive executions the printed values are not changing - which tells me that the locations in memory are the same each time they execute.
I'm just curious as to how this is determined, why this is so.
Those variables live on the stack. The execution of your program looks to be deterministic, so every time you run it the same things happen. It's not choosing the same address necessarily (many runtimes these days make use of Address Space Randomization techniques to ensure that the stack addresses are not the same between runs), but the relative addresses on the stack contain the same data every time.
They can be anything don't rely on them to be anything specific.
Technically, the values are Indeterminate.
Note that using an Indeterminate value results in Undefined Behavior.
They're all stack based. Probably the startup code has already used those locations, so you're getting whatever it left in them.
The behaviour is not defined as "whatever was stored in that memory location previously", but it is rather not defined at all. There is no guarantee to what will happen.
My best guess is that your operation system is using virtual memory (as most modern OS do), thus giving you the same memory addresses every time.
Unlike humans, computers are deterministic.
Usually a good idea to use the compiler options to pick up when reading a variable that has not been given a value.
So the OS picks up the code and does exactly the same thing ever time. Hence the same result.
But if you start fiddling with the code the executable will be different. As you have not been specific you get a different result the next time around.
So in summary just use all the features of the compiler to help you spot this error and get into the habit of giving the variables values before using that variable.
Related
This question already has answers here:
What does "dereferencing" a pointer mean?
(6 answers)
Closed 2 years ago.
I am new to C++, but I am curious enough to dig into these strange things.
I was wondering what happens when I convert a pointer to an int and realized could they indicate something. So I wrote this program to test my ideas as pointers in the same array are close enough in terms of memory location to be compared.
This is the code that will explain my question clearly.
#include <iostream>
using namespace std;
int main() {
cout << "--------------------[ Pointers ]--------------------" << endl;
const unsigned int NSTRINGS = 9;
string strArray[NSTRINGS] = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" };
string *pStartArray = &strArray[0]; // Setting pStartArray pointer location to the first block of the array.
string *pEndArray = &strArray[NSTRINGS - 1]; // Setting pEndArray pointer location to the last block of the array.
cout << "---[ pStartArray value : " << *pStartArray << endl; // Showing the value of the pStartArray pointer (Just for safety check).
cout << "---[ pEndArray value : " << *pEndArray << endl; // Showing the value of the pEndArray pointer (Just for safety check).
short int blockDifferential = pEndArray - pStartArray; // Calculating the block differential of those two pointers.
cout << "---[ Differential of the block locations that pointers are pointing to in array (pEndArray - pStartArray) : " << blockDifferential << endl;
long long pStartIntLocation = (long long)pStartArray; // Converting the memory location (Hexadecimal) of pStartArray pointer to int (Maybe it's byte, regardless of being positive or negative). What's your opinion on this?
cout << "---[ (long long) pStartArray current memory location to int : \"" << pStartIntLocation << "\"" << endl;
long long pEndIntLocation = (long long)pEndArray;
cout << "---[ (long long) pEndArray current memory location converted to int : \"" << pEndIntLocation << "\"" << endl; // Converting the memory location (Hexadecimal) of pEndArray pointer to int (Maybe it's byte, regardless of being positive or negative). What's your opinion on this?
short int locationDifferential = pEndIntLocation - pStartIntLocation; // And subtracting the integer convetred location of pEndArray from pStartArray.
cout << "---[ Differential of the memory locations converted to int ((long long)pStartArray - (long long)pEndArray) : " << locationDifferential << " (Bytes?)" << endl; // Seems like even after running the program multiple times, this number does not change. Something's fishy. Doesn't it seem like it's a random thing. It must be investigated.
cout << "---[ Size of variable <string> (According to the computer that it's running) : " << sizeof(string) << " (Bytes)" << endl; // To know how much memory does a string consume. For example mine was 40.
// Here it goes interesting. I can get the block differential of the pointers using <locationDifferential>.
cout << "---[ Differential of the cell location (AGAIN) using the <locationDifferential> that I have calculated : " << locationDifferential/sizeof(string) << endl; // So definately <locationDifferential> was in bytes. Because I got 8 again. I just wonder is it a new discovery. LOL.
/*
I might look really crazy, because I can't tell it another way. It just can't happen.
This is the last try to make it as clear as I can.
pStrArray ]--\ pEndArray ]--\
\ - 8 cell difference - \
Array = | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|-------- Differential ---------|
Cell difference : 8 string cells
String size that I considered : 32 Bytes
data (location difference) : 8 * 32 = 256
So if you see this, all this might make sense.
I am excited to see what opinions you professional programmers have come up with.
- D3F4U1T
*/
cout << "----------------------------------------------------" << endl;
return 0;
}
How does this exactly work?
pStartIntLocation, pEndIntLocation are all in bytes?
If so, why sometimes they return negative value?
This is strange.
Also correct me if I am wrong about any information I provided.
- Best regards.
- D3F4U1T.
Edit 2:
Does the value that results from the conversion from pointer to a long long mean anything? Like the memory address but with the difference that this one is in bytes?
Edit 3: Seems like this is related to virtual address space. Correct me if I am wrong. Does the OS have any mechanism to number the memory as bytes. For example: Byte 1 , Byte 2 , ....
A "pointer" is an integer quantity of some length whose contents are understood to represent a memory address. (By convention, zero means NULL ... no address.)
If you typecast it into an integer, you are simply declaring to the compiler that *"no, these however-many bits should not be treated as an address ... treat them as an integer." The content of the location does not change, only the compiler's interpretation of it.
Typecasting does not change the bits – only the momentary interpretation of what they are and what they mean.
FYI: unions are another way to do a similar thing: every element of a union overlaps the others and describes various interpretations of the same area of storage. (In the Fortran language, this was called EQUIVALENCE.)
We know that strcat() recevies a poiner to a destination array as parameters and concatenate them with source string. The destination array should be large enough to store the concatenated result. Recently i found out that it is still possible for strcat() to execute as expected, for small programs, even when the destination array is not large enough to add second string. I start surfing stackoverflow and found out couple -
answers for this question. I want to go more deeply,and understand what exactly happends in hardware layer when i run this code below ?
#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstring>
using namespace std;
int main(){
char p[6] = "Hello";
cout << "Length of p before = " << strlen(p) << endl;
cout << "Size of p before = " << sizeof(p) << endl;
char as[8] = "_World!";
cout << "Length of as before = " << strlen(as) << endl;
cout << "Size of as before = " << sizeof(as) << endl;
cout << strcat(p,as) << endl;
cout << "After concatenation:" << endl;
cout << "Length of p after = " << strlen(p) << endl;
cout << "Size of p after = " << sizeof(p) << endl;
cout << "Length of as after = " << strlen(as) << endl;
cout << "Size of as after = " << sizeof(as) << endl;
return 0;
}
After running this code the length of array p[] is 12, and the size of p[] is 6. How can physically such length be stored on such array size ? I mean for this array the number of bytes are limited, so does it mean that strlen(p) function looks only for NULL terminator, and keeps counting untill it founds it and ignores the actual allocated size of that array. And sizeof() function doesn't really care if the last element in array, allocated purposely for null-character, is stores null-character or not.
The array p is allocated on the function stack frame, so strcat "overflows" the buffer p and continues wrting to some other area of the stack - typically it overrides other local parameters, function return address, etc (keep in mind that on x86 platform function stack usually grows "downwards", i.e. towards lesser addresses). This is well-known "buffer overflow" vulnerability.
strlen cannot know what is the actual size of your buffer, it just looks for 0-terminator. On the other hand, sizeof is a compile-time function that returns the array size in bytes.
You are writing outside the bounds of p and the behavior of your program is therefore undefined.
While the behavior is totally undefined, there are a couple of common behaviors that occur:
You overwrite some unrelated data. This could be other local variables, the function return address, etc. It's impossible to guess exactly what will get overwritten without examining the assembly generated by the compiler for that specific program. This can result in a severe security vulnerability since it can allow an attacker to inject their own code into your program's memory space and let them overwrite a function's return address to cause the program to execute their injected code.
The program crashes. This can happen if you write far enough past the end of the array to pass a memory page boundary. The program can try to write to a virtual memory address that the OS hasn't mapped to physical memory for your application. This results in the OS killing your application (with a SIGSEGV on Linux, for example). This will usually happen more often with dynamically allocated arrays than function-local arrays.
I am facing issue with result output with long int. Here Below is my Program, I am calculating tax with various methods 1) taking result output in int and long variable. I think all the four results in my code should be the same, but result output in tax3 variable is coming different (less by 1) than other three. please help me to understand the reason.
#include<iostream.h>
#include<conio.h>
int main()
{
long salary;
cout << "Enter Salary: " << endl;
cin>>salary;
float tax1, tax2;
long tax3, tax4;
tax1 = salary*0.15;
tax2 = (salary*15)/100;
tax3 = salary*0.15;
tax4 = (salary*15)/100;
cout << "tax1=" << tax1 << endl;
cout << "tax2=" << tax2 << endl;
cout << "tax3=" << tax3 << endl;
cout << "tax4=" << tax4 << endl;
getch();
return(0);
}
There are two major types of numbers which are known by the compiler - floating points and Integers. The floating points follows IEEE-754 floating point for representation for 32 bit(float) and 64 bit(double). In turbo C the int is only 16 bits. Also when you copy from float to int only integer part is copied. i.e. consider the following example :
float a=9.8;
int b=(int)a;
In above code when you print b it will give only 9. Also a piece of advice for you, if you want to learn c++ better then please switch from turbo c to gcc.
In a simple console application I am trying to read a file containing a hex value on each line.
It works for the first few, but after 4 or 5 it starts outputting cdcdcdcd.
Any idea why this is? Is there a limit on using read in this basic manner?
The first byte of the file is its size.
std::ifstream read("file.bin");
int* data;
try
{
data = new int [11398];
}
catch (int e)
{
std::cout << "Error - dynamic array not created. Code: [" << e << "]\n";
}
int size = 0;
read>>std::hex>>size;
std::cout<<std::hex<<size<<std::endl;
for( int i = 0; i < size; i++)
{
read>>std::hex>>data[i];
std::cout<<std::hex<<data[i]<<std::endl;
}
The values I get returned are:
576 (size)
1000323
2000000
1000005
cdcdcdcd
cdcdcdcd
cdcdcdcd
...
The first value that is meant to be output in cdcdcdcd's place is 80000000.
You are overflowing an int.
If you change to unsigned int. You will be able to fill to 0xFFFFFFFF
You can check with:
std::cout << "Range of integer: "
<< std::numeric_limits<int>::max()
<< " <Value> "
<< std::numeric_limits<int>::min()
<< "\n";
std::cout << "Range of integer: "
<< std::numeric_limits<unsigned int>::max()
<< " <Value> "
<< std::numeric_limits<unsigned int>::min()
<< "\n";
Note: There is no negative hex values (it is designed as a compact representation for a bit representation).
You should really check that the read worked:
if (read>>std::hex>>data[i])
{
// read worked
}
else
{
// read failed.
}
It sounds very much like your read fails.
Note that on a 32-bit int system, 0x80000000 is out of range for int. The range of valid values is probably -0x80000000 through to 0x7FFFFFFF.
It's important not to mix up values with representations. "0x80000000" , when read via std::hex, means the positive integer which is written as 80000000 in base 16. It's neither here nor there that a particular negative integer may be stored internally in a signed int in 2's complement with the same binary representation as a positive value of type unsigned int has when the positive integer 80000000 is stored in it.
Consider reading into unsigned int if you intend to use this technique. Also, it is essential that you check the read operation for success or failure. If a stream extraction fails then the stream is put into an error state, where all subsequent reads fail until you call .clear() on the stream.
NB. std::hex (and all other modifiers actually) are "sticky": once you set it, it stays set until you actually specify std::dec to restore the default.
I'm working on union using c++,
following is code snippet:
#include<iostream>
using namespace std;
typedef union myunion
{
double PI;
int B;
}MYUNION;
int main()
{
MYUNION numbers;
numbers.PI = 3;
numbers.B = 50;
cout <<" numbers.PI :" << numbers.PI << endl;
if(numbers.PI == 3.0)
{
cout <<"True";
if(numbers.B == 50)
{
cout <<" numbers.PI :" << numbers.PI << endl;
cout <<" numbers.B :" << numbers.B << endl;
}
}
return 0;
}
Output is:
numbers.PI :3
Even value of numbers.PI is set to 3 already, first "if" condition yields to false.
what is the reason of this behavior?
The reason is that there's no reason.
Your code invokes undefined behavior because you are setting the B member of the union:
numbers.B = 50;
but immediately after setting it, you read out the other member, PI:
cout <<" numbers.PI :" << numbers.PI << endl;
Maybe you are confusing unions and structures - unless the floating-point number 3 and the integer 50 have the very same bit representation on your architecture (which is very unlikely), the behavior you expect from your program would be reasonable only if you used a struct instead.
(union members reside at the same place in memory - setting one overwrites the other too. This is not true for a struct, which has each of its members stored at a different memory location.)
Remember that all members of a union shares the same memory. When you assign to B you change the value of PI as well.
To be safe, you should only "read" from the last field you "write" to.
It seems to me that what you want is a structure.
You're getting undefined behavior, but here's what is happening behind the scenes:
You're using a little-endian machine with sizeof(int) < sizeof(double), such as an x86. Almost certainly, the machine uses IEEE 754 format for floats/double (pretty much all machines do these days).
When you write into the B field, it overwrites the low order bits of the double in PI. So
when you initially store 3.0 in PI, that sets it to something like 0x4008000000000000. Then when you store 50 in B that changes PI to 0x4008000000000032, which happens to be 3.00000000000002220446049250313080847263336181640625. So that's not equal to 3.0, but when you print it with default precision, it rounds it to 3.0