Use an un-initialized pointer as a function parameter - c++

As I want to pass an uninitialized pointer to a function, it goes runtime error.
but if I pass this pointer as a reference, it works OK. I cannot explain why...
class Body
{
};
void check(Body* b)
{
b = new Body();
}
void checkRef(Body* &b)
{
b = new Body();
}
int main001()
{
Body* b;
//check(b);// error: The variable 'b' is being used without being initialized. (in VS2010)
checkRef(b); // OK
return 0;
}
Whats the difference when b is passed to check and checkRef? I get the runtime error in VisualStudio2010. error:The variable 'b' is being used without being initialized.
EDIT: it was a VS2010 debug output. the "error" doesn't appear in release version

In order to be equivalent to the checkRef version, your check function should read:
void check(Body** b)
{
*b = new Body();
}
and called as
check(&b);
If you don't pass the address, as you do in check(b), then you are passing the current value of the pointer b which is indeed uninitialised.

Body* b does not set b to point to anything sensible. So it may point to some random location which could cause the earth to shift a bit.
Passing it to check(by value for the pointer) does not make it initialised in any way
void check(Body* b)
{
b = new Body();
}
If you passed it by pointer to pointer, it should be okay
void check(Body** b)
{
*b = new Body();
}
And the call
check(&b);
Better done in C++ way with the reference example you give since that updates the referenced pointer value to point to the newly allocated Body

In Body * &b b is an alias of/reference to the b in main - so when you assign to it you modify the b in main. In Body* b b is a local copy of the b in main, you're modifying this local copy and not the b in main.
Your runtime error is likely due to using the uninitialized b in main.
EDIT: The actual error you get is an extra check-for-typical-problems mechanism embedded into your code by your compiler. It detects that you pass something uninitialized by value, which doesn't make sense, and therefore generates this error.
If you disable this behavior, the application will appear to function properly until you try to dereference the uninitialized b in main

I don't know why you're seeing a run-time error; at most I would expect to receive a compile-time warning/error. But you can probably fix it by initialising b to NULL (but this won't fix your program; see below...)
The difference between the first and the second function call is that the first one will cause a memory-leak. You are passing the pointer by-value, so inside check() you are working with a copy of that pointer. You assign this copy, but this doesn't affect the value of the pointer in main(), so when you leave the function, there is no way to access the memory that was obtained by new.

Related

Return object with 2 optional ctors in function

I have function in c++ with 2 optional c'tor of an object I've built (one with something in vector "vals" and other without).
...
RecievedMessage a(sc, type);
if (!vals.empty()){
//a.~RecievedMessage();
RecievedMessage a(sc, type, vals);
}
return &a;
}
the line in // is optional.
Would it work (with or without the optional line)? Why? If no, how to fix it without setter for "vals"?
thanks a lot.
No, it wouldn't work.
RecievedMessage a(sc, type);
// Here we construct 'a'
if (!vals.empty()){
//a.~RecievedMessage();
// If we enable this line, we destroy 'a'
RecievedMessage a(sc, type, vals);
// Here we construct a second 'a' that only exists in this block
}
// End of block: The inner 'a' is destroyed here automatically
return &a;
}
// End of block: The outer 'a' is destroyed here, again.
Destroying an object twice has undefined behavior. You don't want that.
If you don't call the destructor manually, the outer a is only destroyed once, which is good.
But in either case, RecievedMessage a(sc, type, vals); has nothing to do with the outer a and merely creates another variable.
There would be ways to work around that, but the final line of your code makes it all pointless:
return &a;
You're returning the address of a local variable. This is broken in and of itself: When the function returns, all of its local variables are destroyed automatically, so what you're returning is an invalid pointer.
Your code is all over the place, but what I think you're looking for is something like this:
ReceivedMessage *MakeReceivedMessage (foo sc, bar type, vector<whatever>& vals)
{
if (vals.empty())
return new ReceivedMessage (sc, type);
return new ReceivedMessage (sc, type, vals);
}
Of course, it would be better in this example to just have a single constructor and have the object test whether vals is empty when appropriate, but, in general, you can call whatever constructor you like whenever you like. Just manage your object lifetimes properly (and don't - ever - return a pointer to an object on the stack).
Example usage (to manage the lifetime of the object returned properly):
std::unique_ptr<ReceivedMessage> MyReceivedMessage (MakeReceivedMessage (...));
MyReceivedMessage->DoFunkyStuffWithMessage ();
....
Or, as melpomene points out, you can return a std::unique_ptr<ReceivedMessage> in the first place. Some (many?) would prefer that. You can construct it with std::make_unique.
There are three main issues with your code right now:
First of all, your commented out call to the destructor ~ReceivedMessage() should not be there at all. In C++, the destructor of objects is automatically called when an object's lifetime ends (either when it goes out of scope, or when delete is called if it was dynamically allocated with new). While there are some situations where explicitly calling a destructor is necessary ("placement new" for example), these are situations you're very unlikely to come across.
Secondly, your RecievedMessage a(sc, type, vals); declaration in the inner if does not replace the value of a in the outer scope. This just creates another variable of the same name which shadows the outer a, while return &a; in the outer scope can only refer to the outer a. The inner a no longer exists at this point as it has gone out of scope.
A way to fix this issue is to instead assign a new value to a by using the = operator and constructing a temporary ReceivedMessage:
if (!vals.empty()) {
a = ReceivedMessage(sc, type, vals);
}
This should work as long as a correct operator= is defined (implicitly or otherwise) for ReceivedMessage.
Thirdly, your function is returning a pointer to the local variable a. Since objects in C++ are destroyed as soon as they go out of scope, a no longer exists by the time the function has returned, so the ReceivedMessage * pointer the calling code obtains is invalid and it would be undefined behaviour to dereference that pointer and make use of it.
There are a couple of fixes to this issue:
The first option is instead of returning a pointer (ReceivedMessage *), just return a ReceivedMessage by value.
ReceivedMessage foo()
{
ReceivedMessage a(123);
return a;
}
This should work as long as a correct copy or move constructor is defined (implicitly or otherwise) for ReceivedMessage.
The second option is to make use of std::unique_ptr, and make your function instead return std::unique_ptr<ReceivedMessage>.
#include <memory>
std::unique_ptr<ReceivedMessage> foo()
{
std::unique_ptr<ReceivedMessage> a;
if (vals.empty()) {
a = std::make_unique<ReceivedMessage>(sc, type);
} else {
a = std::make_unique<ReceivedMessage>(sc, type, vals);
}
return a;
}
The advantage to this approach is that unique_ptr is nullable, so you can create a null unique_ptr without having to construct a ReceivedMessage straight away. Additionally, you can move and assign unique_ptr values safely without having a correct operator= or a correct copy / move constructor defined.
The calling code may look like this, when using unique_ptr:
std::unique_ptr<ReceivedMessage> message = foo();
foo->bar();
as opposed to the following when using ReceivedMessage directly:
ReceivedMessage message = foo();
foo.bar();

C++ Pointer can call Member Function without Object

Amazingly people may call it feature but I use to say it another bug of C++ that we can call member function through pointer without assigning any object. See following example:
class A{
public:
virtual void f1(){cout<<"f1\n";}
void f2(){cout<<"f2\n";};
};
int main(){
A *p=0;
p->f2();
return 0;
}
Output:
f2
We have checked this in different compilers & platforms but result is same, however if we call virtual function through pointer without object then there occur run-time error. Here reason is obvious for virtual function when object is checked it is not found so there comes error.
This is not a bug. You triggered an Undefined Behavior. You may get anything including the result you expected.
Dereferencing a NULL pointer is undefined behavior.
BTW, there is no thing such as "bug of C++". The bugs may occur in C++ Compilers not in the language it self.
As pointed out, this is undefined behaviour, so anything goes.
To answer the question in terms of the implementation, why do you see this behaviour?
The non-virtual call is implemented as just an ordinary function call, with the this pointer (value null) passed in as paremeter. The parameter is not dereferenced (as no member variables are used), so the call succeeds.
The virtual call requires a lookup in the vtable to get the adress of the actual function to call. The vtable address is stored in a pointer in the data of the object itself. Thus to read it, a de-reference of the this pointer is required - segmentation fault.
When you create a class by
class A{
public:
virtual void f1(){cout<<"f1\n";}
void f2(){cout<<"f2\n";};
};
The Compiler puts the code of member functions in the text area.
When you do p->MemberFunction() then the compiler just deferences p and tries to find the function MemberFunction using the type information of p which is Class A.
Now since the function's code exists in the text area so it is called. If the function had references to some class variables then while accessing them, you might have gotten a Segmentation Fault as there is no object, but since that is not the case, hence the function executes properly.
NOTE: It all depends on how a compiler implements member function access. Some compiler may choose to see if the pointer of object is null before accessing the member function, but then the pointer may have some garbage value instead of 0 which a compiler cannot check, so generally compilers ignore this check.
You can achieve a lot with undefined behavior. You can even call a function which only takes 1 argument and receive the second one like this:
#include <iostream>
void Func(int x)
{
uintptr_t ptr = reinterpret_cast<uintptr_t>(&x) + sizeof(x);
uintptr_t* sPtr = (uintptr_t*)ptr;
const char* secondArgument = (const char*)*sPtr;
std::cout << secondArgument << std::endl;
}
int main()
{
typedef void(*PROCADDR)(int, const char*);
PROCADDR ext_addr = reinterpret_cast<PROCADDR>(&Func);
//call the function
ext_addr(10, "arg");
return 0;
}
Compile and run under windows and you will get "arg" as result for the second argument. This is not a fault within C++, it is just plain stupid on my part :)
This will work on most compilers. When you make a call to a method (non virtual), the compiler translates:
obj.foo();
to something:
foo(&obj);
Where &obj becomes the this pointer for foo method. When you use a pointer:
Obj *pObj = NULL;
pObj->foo();
For the compiler it is nothing but:
foo(pObj);
i.e.:
foo(NULL);
Calling any function with null pointer is not a crime, the null pointer (i.e. pointer having null value) will be pushed to call stack. It is up to the target function to check if null was passed to it. It is like calling:
strlen(NULL);
Which will compile, and also run, if it is handled:
size_t strlen(const char* ptr) {
if (ptr==NULL) return 0;
... // rest of code if `ptr` is not null
}
Thus, this is very much valid:
((A*)NULL)->f2();
As long as f2 is non-virtual, and if f2 doesn't read/write anything out of this, including any virtual function calls. Static data and function access will still be okay.
However, if method is virtual, the function call is not as simple as it appears. Compiler puts some additional code to perform late binding of given function. The late binding is totally based on what is being pointed by this pointer. It is compiler dependent, but a call like:
obj->virtual_fun();
Will involve looking up the current type of obj by virtual function table lookup. therefore, obj must not be null.

C++ NULL pointers and const correctness

I read that it is good practice to do a check in the destructors of classes after deletion for pointer data members as follows:
if( 0 != m_pPointer)
{
delete m_pPointer;
m_pPointer= 0;
}
However, I found out that this prevents you to declare const pointers as data members as follows:
Type* const m_pPointer;
Isn't assigning NULL to pointers(as in my example above) a barrier for const-correctness?
What is the best way to do? Keep everything const and stop assigning NULL to the deleted pointer or declaring non-const pointers even though their address never changes?
This is bad practice for the following reasons:
Setting a pointer to null in the destructor may mask double destruction problem. Good practise is to detect problems as early as possible.
Checking a pointer for null before deleteing it only adds unnecessary code. delete handles null pointers by doing nothing. Good practice is to minimize the amount of code.
Deleting a null pointer is guaranteed safe, so that null check is pointless.
If a class has a member that is a const pointer to a non-const object then you're saying the pointer value WILL NOT change within the lifetime of the wrapping object - that being the case you should only do this in the case where the object pointed to will live as long or longer than the wrapping object and the wrapping object will never want to point to a different object.
The fact that you have this issue simply means you've used a const pointer in the wrong place. You claim that in your case the pointer value never changes, but in your example it obviously does - it changes to null.
The "best way to do" is:
class foo {
std::unique_ptr<bar> m_pPointer;
public:
foo(std::unique_ptr<bar> pPointer)
: m_pPointer{std::move(pPointer)} {}
};
or for const,
class foo {
const std::unique_ptr<bar> m_pPointer;
public:
foo(std::unique_ptr<bar> pPointer)
: m_pPointer{std::move(pPointer)} {}
};
No new, no delete, no destructor.
A weird situation can be caused when you link a static lib with a global or static object from two different shared libs (on Linux) which later be linked to the same executable.
Each shared lib object insert call to constructor and destructor, so you'll have one object and two calls for constructor and destructor for the same object (actually you'll have 2 objects mapped to the same address).
You'll probably find the problem when your app crash in the 2nd destructor.
if you NULL it you'll never know that there was a problem at all.
for your question: except for the above issue, I think you should distinct two types of pointers:
See the class below:
class A{
obj *x, *y;
A(){
x = new obj;
y = NULL
}
~A(){
delete x;
if(y)delete y; // the `if` here will save the calling and returning run time when NULL.
}
void RecicleX(){
delete x;
x = new obj;
}
void InitY(){
assert(y==NULL); //illegal to call init when already
y = new obj;
}
void TermY(){
assert(y); //illegal to call term when already inited
delete y;
y = NULL; //prevent crush in dtor if called after...
}
};
x is always exists, so no need to check it, and no need to null it. y may exists and may not, so I think you should null it after deletion.
(You maybe will want also to know the current state, like for assert)

Pointer to a object that scoping in the function

I just think of a question about pointer,
the pointer p first initial in main function and point to object "a"
and then call function f , and change to point object "b".
but the scope of "b" is only in function. After call the function f, why the pointer p is still pointer to "a". Shouldn't p be NULL or something else?
void f(int*p){
int b = 10;
p = &b;
}
int main(){
int*p1 = NULL;
int a=6;
p1 = &a;
f(p1);
cout<<*p1<<endl;//output 6
cout<<a<<endl;//output 6
return 0;
}
C++ functions has value semantics , function f copies pointer p1, original p1 is not modified.
In f function, you tried to point pointer to local variable, this is dangerous.
If you intent to modify pointer p points to, you need to pass the address of pointer
void f(int*& p) // pass in reference to pointer
{
static int b = 10; // make it static,
// so p won't become dangling pointer when f returns
p = &b;
}
What happens:
Because you pass pointer by value, a local copy is created in function f, Then you assign another value (pointer to b) to that copy and leave the function. Original pointer remains unchanged.
Now let's suppose, that you modify the function in the following way:
void f(int * & p){
int b = 10;
p = &b;
}
Don't do this at home!
Now, the actual pointer is passed to function, no copy is created. Then a pointer to b is assigned to it and function returns.
Then you try to access the value pointed to by p1 - a value, which is no longer valid, because b no longer exists. You get an undefined behavior here: the best case scenario is that everything actually will work as you guess it would, the worst case scenario is that you'll get an Access Violation or worse - some data of your program may get corrupted (everything depending on platform and compiler).
Why C++ compiler doesn't notify you about that? Generally because C++ is not supposed to take care of you, such that you won't shoot yourself in the foot (actually, there are so many ways to shoot yourself in the foot using C++, that if you stack books containing these, you would reach Moon). C++ just does what you tell it to. You want to get pointer to b? Ok, no problem. You want to return a pointer from function? Why not, that's simply a 32-bit integer value.
The point is, that when writing in C++, you have to be very cautious not to write such code.
Edit: in response to comments
Imagine, that data is a building and pointer is a piece of paper with address of that building. When you pass pointer by value:
void f(int * p)
It is like you took another piece of paper and copied the address. If you then erase it and change to another one, the original address on the original piece of paper will remain unchanged.
Now if you do something like:
void f(int * p)
{
*p = 4;
}
It's like you actually went to the address written on the piece of paper and changed something in the building. If you then go to the address stored on the original piece of paper, the building will be changed.
Finally, if you do something like:
void f(int * & p)
{
}
It's like you passed the original piece of paper to the function, so if you change the address, it is changed also outside of the function.
Hope this helps you to understand how pointers work.
Here the pointer is passed by value i.e the function f makes a copy of it then uses it, and when it is done it destroys it. the initial pointer p1 is unchanged.
When your pointer becomes invalid, it doesn't magically take on a different or null value. It still points to the same place; it's just that that place is no longer valid.

in c++, what is the difference between two function calls that use pointers?

In the first function call, I'm sending in a matrix pass by reference. Isn't the second way the same? I thought matrices were default pass by reference.
Here's the first case:
phi= new double[15]; //phi is a dynamically allocated array
function(double *phi) //calls phi with what SHOULD be default pass by reference
Second case:
function(double *&phi) //calls phi with pass by reference?
There should be no difference between the two, right?
The reason I ask is because my code segment faults when I neglect the '&' sign and try to assign a value to phi outside of the function that I dynamically allocated it in.
In the first case, your function declaration accepts a pointer by value.
In the second case, your function declaration accepts a pointer by reference. You could change the pointer in the function.
You seem to be misunderstanding what "passing as reference" means. When you pass a variable as a reference, you give the function the ability to change the value of the variable.
Say I have a function defined as:
doIt(int i)
and I call it like this:
main()
{
int a = 2;
doIt(a);
}
The function can't change the value of the "a" variable.
In your case, you are using a pointer. If I had the following function:
doItWithAPointer(int* a)
and called it like this:
main()
{
int a = 2;
int* pa = &a;
doItWithAPointer(pa);
}
I could now change the value of "a". Why? because I can access its value through the pointer. What I can't do is change the value of the actual parameter, in this case "pa" or, in other words, make it point to another address.
Now, finally if I declare my function like this:
doItWithAPointerReference(int* &a)
and called it like this:
main()
{
int a = 2;
int* pa = &a;
doItWithAPointerReference(pa);
}
I can still change the value of the "a" variable through the pointer, but I can also directly change the value of "pa" since I have a reference to it!