int func() {
int a;
++a; // is this safe?
printf("%d\n", a);
}
I know when I printf a I get undefined behavior, but is ++a safe in C++ standard? Will this assign "another" uninitialized value to a without side effects (throwing exceptions or crashing the program)?
Using an uninitialized variable in anyways gives you Undefined behavior. So,
No incrementing an uninitialized int is not safe in C++.
Your program might not crash but it is certainly not safe. You should always initialize your variables. The worst that can happen is your program will appear to work but will crash at random times without you knowing the cause or simply behave in a strange way.
What do you mean by "undefined behaviour"? In my opinion your program should print some int without any exceptions and so on.
++(uninitizalized int) is absolutely legal, I guess. It will just increment the current value, no matter whether the var was initialized or not.
But anyway, uninitialized vars are EVIL.
Related
struct Foo{
int i;
int j;
};
int main(){
std::allocator<Foo> bar;
Foo* foo = bar.allocate(1);
foo->i = 0;
return foo->i; // ignore the memory leak, it's irrelevant to the question
}
I'm curious about whether there are undefined behaviors in the snippet above? Will the conclusion vary according to the type of Foo (e.g. not all members are POD type, or Foo has virtual functions)?
It is an error to use raw memory in which an object has not been constructed.
We must construct objects in order to use memory returned by
allocate. Using unconstructed memory in other ways is undefined. Source: C++ Primer, Fifth Edition
Since you have not used construct the behavior of your program is undefined prior to C++20.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.
I am new to programming and am currently studying about address typecasting. I don't seem to understand why I am getting this : *** stack smashing detected ***: terminated Aborted (core dumped) when I run the following code??
#include<iostream>
using namespace std;
void updateValue(int *p){
*p = 610 % 255;
}
int main(){
char ch = 'A';
updateValue((int*)&ch);
cout << ch;
}
Here's what I understand about the code:
The address of ch is typecasted to int* and passed into the function updateValue(). Now, inside the updateValue() stack, an integer pointer p is created which points to ch. When p is dereferenced, it interprets ch as an int and reads 4(or 8) bytes of contiguous memory instead of 1. So, 'A'(65) along with some garbage value gets assigned to 610%255 i.e. 20.
But I don't understand, what and where things are going wrong?
when p is dereferenced, it interprets ...
When you indirect through the reinterpreted p and access an object of the wrong type, the behaviour of the program is undefined.
what and where things are going wrong?
Things started going wrong when you reinterpreted a pointer to one type as a pointer to an unrelated type.
Some rules of thumb:
Don't use reinterpret casts until you know what it does. They are difficult to get right, and are rarely useful.
Don't use reinterpret casts when it would result in undefined behaviour.
Don't use C-style casts at all.
If you think that you need to reinterpret cast, then take a few steps back, and consider why you think that you need it.
The problem is that you're typecasting a char* to an int* and then dereferencing p which leads to undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash which happens in your case.
For example, here the program crashes, but here it doesn't crash.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.
But I don't understand, what and where things are going wrong?
In this statement
*p = 610 % 255;
the memory that does not belong to the object ch that has the type char is overwritten. That is instead of one byte occupied by the object ch there are overwritten 4 bytes that correspond to the allocated memory for an object of the type int.
This question already has answers here:
Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior?
(7 answers)
Closed 4 years ago.
#include <iostream>
using namespace std;
int main() {
int *a;
int *b;
int c=12;
a=&c;
*b=*b;
cout << *b << endl;
}
The above code works fine, but the following code returns a segmentation fault error
#include <iostream>
using namespace std;
int main() {
int *a;
int *b;
int c=12;
//a=&c;
*b=*b;
cout << *b << endl;
}
Why?
gcc (Ubuntu 8.2.0-7ubuntu1) 8.2.0
Here's a step-by-step breakdown of what your code is doing:
int *a;
int *b;
This declares two pointers to int named a and b. It does not initialize them. That means that their values are unspecified, and you should expect them to be complete garbage. You can think of them as "wild" pointers at this moment, which is to say that they don't point to valid objects, and dereferencing them will cause Undefined Behavior and introduce a plethora of weird bugs, if not a simple crash.
int c=12;
This creates a simple local variable c of type int, which is initialized, with a value of 12. If you hadn't initialized it, as in int c; then it would also be full of garbage.
a=&c;
This snippet sets the pointer a to point to c, which is to say that the address of c is assigned to a. Now a is no longer uninitialized, and points to a well-defined location. After this, you can safely dereference a and be assured that there is a valid int at the other end.
*b=*b;
Here, you are dereferencing b, which means that you are reaching into your programs memory to grab whatever is pointed to by b. But b is uninitialized; it is garbage. What is it pointing to? Who knows? To read from the address it points to is like Russian roulette, you might kill your program immediately if you get really unlucky and the Operating System or runtime environment notices you doing something that's obviously wrong. But you also might get away with it, only for weird and unpredictable bugs to emerge later. This weirdness and unpredictability is why a good C++ programmer avoids Undefined Behavior at all costs, and ensures that variables are initialized before they are used, and makes sure that pointers are pointing to valid objects before dereferencing them.
Why does there appear to be a difference depending on a=&c;?
As to why your program apparently crashes or doesn't crash depending on how you initialize the other pointer, the answer is that it doesn't matter. In both cases, you're causing Undefined Behavior; you are breaking the language's rules and you should not expect the language to behave correctly for you thereafter, and all bets are off.
"*b=*b" - Is broken code. b is uninitialised, so you are dereferencing an uninitialised pointer. That's Undefined Behaviour. The program is broken and has no meaning according to the standard and the compiler is allowed to generate whatever code it feels like (no diagnostic required).
To be clear, I am aware of pointer to pointer concept in C and of dereferencing double, triple pointers. The only doubt I have is in the following program which I wrote:
#include<stdio.h>
int main(){
int a;
int* p;
a=5;
p=&a;
int **q;
printf("*p=%d\n",*p);
printf("*q=%d\n",*q);
}
Now I know, the program is quite stupid and makes no sense, but that's not the problem. The question is WHY?
Why is the Output like this:
*p=5
*q=1
Why is *q=1 on every run?
Also it is to keep in mind, if I now declare a ***r;
And add the following line:
printf("*r=%d\n",*r);
Now the output is :
*p=5
*q=-40821602 //garbage
*r=1
Now, *r=1. WHY?
Same goes for ****s. In that case, *q,*r is a garbage and *s=1. Why?
Evaluation of an uninitialized pointer is undefined behavior, and that is what you did. cppreference states the following on undefined behavior:
Undefined Behavior:
undefined behavior - there are no restrictions on the behavior of the program. Examples of undefined behavior are memory accesses outside of array bounds, signed integer overflow, null pointer dereference, modification of the same scalar more than once in an expression without sequence points, access to an object through a pointer of a different type, etc. Compilers are not required to diagnose undefined behavior (although many simple situations are diagnosed), and the compiled program is not required to do anything meaningful.
Hence, you cannot expect anything meaningful coming out of your program. It may print 1, but it could also do anything else. In my case, for example, it simply crashed.
So the question "why?" is simply not a valid question.
I have bad function that returns reference to dead string:
std::string & ffff()
{
std::string j = "12346";
return j;
}
And if I call std::string ii = ffff(); I have crash. That is correct and understandable.
But now I have function that returns reference to int:
int & ff()
{
int g = 1;
return g;
}
And I can't understand why I have no crash when I try assign reference of "dead" int g to int i variable.
int i = ff();
The C++ standard does not contain a notion of "crash". There is no standard-conforming, deterministic mechanism by which you can "cause a crash".
The behaviour of your program is undefined, so the language standard does not describe what will and should happen.
As already has been said, you are in the land of "undefined behaviour" and you should expect that: behaviour that may not be "correct and understandable".
If you want to understand what is the compiler doing, then look at the assembler generated. There you will be able to see what is happening, and why there is a crash.
My guess (although I may be wrong) is that the string is destroyed when exiting the function, so it is clearly a "dead string" (using your own terms, not a very rigorous one). On the other hand, returning a reference of an int... the int is not "destroyed" as it is not an object. The compiler probably does a pass by value to simplify things --you return a reference to immediately copy it? the compiler should see through that. Even if you encapsulated it in an object, the memory of an int is constant so it should still be there and probably available even when destroyed.
Anyway, I see that you have been downvoted, as it is not a very interesting question by itself. You are asking why something doesn't crash while using bad programming practices, and this is not constructive --I will not downvote, as I also am a genuinely curios programmer ;)