Default values for implicit Default constructor in C++ - c++

I was going through the C++ Object model when this question came. What are the default values for the data members of a class if the default constructor is invoked?
For example
class A
{
int x;
char* s;
double d;
string str; // very high doubt here as string is a wrapper class
int y[20];
public :
void print_values()
{
cout<<x<<' '<<s<<' '<<d<<' '<<str<<' '<y[0]<<' '<<y<<endl;
}
}
int main()
{
A temp;
temp.print_values(); // what does this print?
return 0;
}

The value of an un-initialized variable is undefined, no matter where the variable lives.
Undefined does not necessarily mean zero, or anything in particular. For example, in many debug builds the memory is filled with a pattern that can be used to detect invalid memory accesses. These are stripped for release builds where the memory is simply left as it was found.

You can't really predict what's going to be in your memory when you're allocating it.
There could be pretty much anything as the memory you're reading has not been set to 0 (or anything else should I say).
Most of the time you'll find the values to be 0 for numeric values in little executables.

Related

How variable 'a' will exist without any object creation?

How variable int a is in existence without object creation? It is not of static type also.
#include <iostream>
using namespace std;
class Data
{
public:
int a;
void print() { cout << "a is " << a << endl; }
};
int main()
{
Data *cp;
int Data::*ptr = &Data::a;
cp->*ptr = 5;
cp->print();
}
Your code shows some undefined behavior, let's go through it:
Data *cp;
Creates a pointer on the stack, though, does not initialize it. On it's own not a problem, though, it should be initialized at some point. Right now, it can contain 0x0badc0de for all we know.
int Data::*ptr=&Data::a;
Nothing wrong with this, it simply creates a pointer to a member.
cp->*ptr=5;
Very dangerous code, you are now using cp without it being initialized. In the best case, this crashes your program. You are now assigning 5 to the memory pointed to by cp. As this was not initialized, you are writing somewhere in the memory space. This can include in the best case: memory you don't own, memory without write access. In both cases, your program can crash. In the worst case, this actually writes to memory that you do own, resulting in corruption of data.
cp->print();
Less dangerous, still undefined, so will read the memory. If you reach this statement, the memory is most likely allocated to your program and this will print 5.
It becomes worse
This program might actually just work, you might be able to execute it because your compiler has optimized it. It noticed you did a write, followed by a read, after which the memory is ignored. So, it could actually optimize your program to: cout << "a is "<< 5 <<endl;, which is totally defined.
So if this actually, for some unknown reason, would work, you have a bug in your program which in time will corrupt or crash your program.
Please write the following instead:
int main()
{
int stackStorage = 0;
Data *cp = &stackStorage;
int Data::*ptr=&Data::a;
cp->*ptr=5;
cp->print();
}
I'd like to add a bit more on the types used in this example.
int Data::*ptr=&Data::a;
For me, ptr is a pointer to int member of Data. Data::a is not an instance, so the address operator returns the offset of a in Data, typically 0.
cp->*ptr=5;
This dereferences cp, a pointer to Data, and applies the offset stored in ptr, namely 0, i.e., a;
So the two lines
int Data::*ptr=&Data::a;
cp->*ptr=5;
are just an obfuscated way of writing
cp->a = 5;

precision about structure loading in memory

typedef struct sample_s
{
int sampleint;
sample2 b;
} sample;
typedef struct sample2_s
{
int a;
int b;
int c;
int d;
} sample2;
int main()
{
sample t;
}
In this example, when I create the instance t of the sample structure, I will also load sample2 in memory.
The Question is, how is it possible to only load the sampleint in the memory ?
Is there a way to only load a part of a structure in memory ?
If the answer is, like I think it is, the inheritance. How does it work exactly ? Will there be a waste of time during the execution due to hash table ?
I am asking those question because I want to develop a DOD (data oriented design) program and I want to understand better how structures are managed in the memory.
Thank you
If you just want to copy sampleint, you can declare int s = x.sampleint; You can also memcpy() a range of memory defined by the offsetof macro in <stddef.h> to get a range of consecutive member variables.
It seems as if what you want is one of the following:
Declare a samplebase type that, in C++, sample can inherit from.
Declare storage for only the individual members you want to copy.
Have sample hold a pointer to a sample2, and set that to NULL if you aren’t allocating one.
Declare the sample as a temporary in a block of code, copy the parts you want, let the memory be reclaimed when it goes out of scope.

default value for a class member in c++

My code is as below: (Tried to made my original code simpler here)
class ExClass {
public:
int check;
ExClass() { }
}
//in main
int main()
{
ExClass *classPtr = new ExClass();
if(classPtr->check == -1)
{
cout<<"check is negative";
}
}
Here the variable 'check' is not initialized in constructor, so it should take some garbage value(as I know).
But my problem here is, it is always printing "check is negative".(so 'check' is -1)
How this happens everytime ? How the variable 'check' is -1 always ?
Thanks for help !
your check is what's called an uninitialized variable:
A common assumption made by novice programmers is that all variables are set to a known value, such as zero, when they are declared. While this is true for many languages, it is not true for all of them, and so the potential for error is there. Languages such as C use stack space for variables, and the collection of variables allocated for a subroutine is known as a stack frame. While the computer will set aside the appropriate amount of space for the stack frame, it usually does so simply by adjusting the value of the stack pointer, and does not set the memory itself to any new state (typically out of efficiency concerns). Therefore, whatever contents of that memory at the time will appear as initial values of the variables which occupy those addresses.
This means the value isn't quite random. But more of a 'whatever the value of the thing before was' thing.
Also note that some compilers (such as visual c++) initialise uninitialised memory with magic numbers (In Visual Studio C++, what are the memory allocation representations?) while in debugging mode.

Segmentation fault when calling virtual method

Here is my code, I casted the buffer to different type of objects, is this what causes the failure? I really want to know why the FromBase::find2(int key) works, but not FromBase::find(int key)?
class Base
{
public:
virtual int find(int key)=0;
int keys[4];
};
class FromBase:public Base
{
public:
FromBase();
int find(int key);
int find2(int key);
};
FromBase::FromBase()
{
for(int i=0;i<4;i++)
keys[i]=-1;
}
int FromBase::find(int key)
{
for(int i=0;i<4;i++){
if(keys[i]==key)
return i;
}
return i;
};
int FromBase::find2(int key)
{
for(int i=0;i<4;i++){
if(keys[i]==key)
return i;
}
return i;
};
int main()
{
FromBase frombase;
FILE* fptr=fopen("object.dat","w");
fwrite((void*)&frombase,48,1,fptr);
fclose(fptr);
char object[48];
fptr=fopen("object.dat","r");
fread((void*)object,48,1,fptr);
// looks like this works
(FromBase*)object->find2(7);
//These two do not work, I got segmentation fault!
(FromBase*)object->find(7);
(Base*)object->find(7);
}
The reason I want to do this is because I need to read the object from a file, thus I need to cast the buffer to an particular type then I can call the mothod.
There is a high chance that you are overwriting the virtual function table with your code leading to a bad address when you call the method. You cannot just save objects into a file and expect to restore them by just restoring the memory content at the time they were saved.
There are some nice libraries like boost::serialization to save and restore objects. I would urge you to read about this or to turn your objects into plain old data types (structs) containing no references or addresses.
There are several reasons why this code is not guaranteed to work. I think the biggest concern is this code here:
char object[48];
The number 48 here is a magic number and there's absolutely no guarantee that the size of the object you're writing out is 48 bytes. If you want to have a buffer large enough to hold an object, use sizeof to see how many bytes you need:
char object[sizeof(FromBase)];
Moreover, this is not guaranteed to work due to alignment issues. Every object in C++ has an alignment, some number that its address must be a multiple of. When you declare a variable, C++ ensures that it has the proper alignment for its type, though there's no guarantee that it ends up having the alignment of any other type. This means that when you declare a char array, there's no guarantee that it's aligned the same way as a real FromBase object would be, and using the buffer as an object of that type results in undefined behavior.
As others have pointed out, though, you also have a problem because this line:
fopen("object.dat","r");
Doesn't update the local variable you're using to keep track of the file pointer, so what you're reading back is almost certainly going to be garbage (if you read back anything at all). The segfault is probably coming from the bytes for the virtual dispatch table not being read back in correctly.
// will these two methods work? I got segmentation fault!
(FromBase*)object->find(7);
(Base*)object->find(7);
No they will not work. The segmentation fault might be a hint ;)
object is a type on the stack, which is fine, but you need to call the class constructor. If this was valid c++, ANY memory could be casted to any class.
I'd start off by creating the class on the stack and call some Load()-method on it, e.g.
FromBase object;
object.Load("object.dat");
And let the Load()-method read the data from file and set values on the internal data.
Apart from all the other problems that people have pointed out.
I absolutely shocked that nobody has mentioned that:
(FromBase*)object->find2(7);
Is just NOT guaranteed to work.
You are depending on a raft of implementation details. object is an array of char! Not a FromBase thus the compiler has not had the chance to initialize any of its implementation dependent details.
Even if we assume that the implementation uses a vtable (and thus a vtable pointer in the class). Does the implementation use a relative pointer or an absolute pointer. Assuming you want to save with one run and then reload the next time? Are you assuming the vtable is actually located in the same location between different runs (what happens when you load this part of the application from a dynamic library)!
This is just horrible. You SHOULD NOT DO THIS EVER.
If you want to serialize and de-serialize the object from storage. Then the class has to know how to do the serialization itself. Thus all the correct constructors/destructors get called at the correct time.
First problem I can see when you use fopen second time:
fopen("object.dat","r"); //problem - your code
which should be this:
fptr = fopen("object.dat","r"); //fix (atleast one fix)
That means, in your code you're trying to read data using fptr which is already closed!
One problem is that the array of characters do not have a method called find.
The cast do not convert the array to FromBase or Base. It only tells the compiler to ignore the error.

how can I corrupt the data segment of a linux process?

I am coding in C/C++. What are the possible ways to corrupt a static variable that is stored in the data segment? Is this considered a memory leak?
#include <stdio.h>
int aaa[5];
int bbb;
int main()
{
int i;
bbb=41;
for (i = 0; i < 6; ++i)
aaa[i] = 42;
printf("%d\n", bbb);
return 0;
}
the code above prints bbb=42 and not 41. this is a possible cause. another way is to modify
static data accessed via multiple threads.
Any other ways?
No, this is not a memory leak. A memory leak is when you allocate on the free store (with malloc/new) and then never free/delete the allocated block.
Note that this is undefined behaviour and is not guaranteed:
int bbb;
int aaa[5];
int main()
{
int i;
bbb=41;
for (i = 0; i < 6; ++i)
aaa[i] = 42;
printf("%d\n", bbb);
return 0;
}
g++ -o test test.cpp && ./test
41
In this particular case bbb is stored after aaa, but you shouldn't be relying on this at all cause it could be somewhere else.
Yes, there is more than one method to destroy the contents of global variables (your variables are not static in the example you posted).
Pointers are a good tool to corrupt memory and write where your program should not. Casting can also add some excitement:
#include <iostream>
using namespace std;
int aaa[5];
int bbb;
int main(void) // Do *your* main() functions always return a value????
{
double * ptr_double = 0;
// Assign the pointer to double to point to the last integer.
// Treat the last integer in the array as a double.
aaa[4] = 45;
cout << "aaa[4] = " << aaa[4] << endl;
ptr_double = (double *)(&aaa[4]);
*ptr_double = 3.14159267;
cout << "aaa[4] = " << aaa[4] << endl;
return -1;
}
With multiple threads, you can have each thread write to the global variable, then have them read back the value. Placing random delays, before writing, and after writing, can show you in more detail how it works.
Another method is to assign the address of your variable to destination register of an I/O hardware device, like a UART. When the UART receives data, it will place that data in that variable, with no regards to the purpose of the variable.
In general values are corrupted by code writing to a location it should not. The primary cause is buffer overrun: Writing more data than is allocated for the variable. Overruns can also occur from hardware devices such as DMA controllers and USB controllers. Another cause is via pointers: the pointer is pointing to an invalid location.
Variables can become corrupted by Stack Overflows and Heap Overflows. On many architectures these structures expand towards each other. Too many variables on the stack, or function recursions (or calling depth) can make the stack overwrite into the heap. Likewise, allocating too much memory from the heap can make the heap overwrite the stack.
Rather than exploring how to damage variables, I believe you should work on improving code safety: design and write your code so it has no buffer overruns, writes to correct locations and shared variables are protected from simultaneous writes by multiple tasks and threads.
All global variables, static or otherwise are initialized to the value specified in their declaration (or zero if not specified) by the loader prior to the execution of any code in the process. The default values will only be modified by code executed within the process (barring any outside interferrence from a debugger).
If you're seeing a "corrupted" value at the beginning of your program's main() function, it's most likely due to a bad action preformed from within the constructor of a global C++ object. The constructors for all global C++ objects are run prior to the invocation of main().
The easiest way to track down the source of this kind of corruption is probably to run the process under a debugger and set a watchpoint on the address of the global variable. The debugger will break when the data is modified. Odds are you have an array overrun or errant pointer problem. They can be a bitch to track down manually.
This is a typical programming error.
You define 5 items of an array of aaa while using 6 aaa's, which means you can only use aaa[0], aaa[1], aaa[2], aaa[3], and aaa[4]. aaa[5] is undefined.
This is a bug, a programming error, and nothing else. Period.