While trying to find out a problem that occurs only in a release build and not in the debug build I noticed the following behaviour (String would be invalid and would not point to anything while the int would be fine). I have given code below which gives an idea of what I was going through
typedef boost::shared_ptr<MyClass> shared_cls
typedef std::deque<shared_cls> vector_def;
typedef boost::shared_ptr<vector_def> shared_vector_def;
typedef boost::unordered_map<int,shared_vector_def> inner_map_def;
typedef boost::shared_ptr<inner_map_def> shared_inner_map_def;
static boost::unordered_map<std::string,shared_inner_map_def> bcontainer;
shared_cls& SomeMethod(const std::string& symb,const int& no)
{
shared_inner_map_def tshare = bcontainer[symb];
shared_vector_def tmp = tshare->at(no);
shared_cls t = tmp->back();
return t
}
The object MyClass looks like this
class SomeClass
{
private:
int i;
std::string s;
void set_i(int rx)
{
i = rx;
}
int get_i()
{
return i;
}
void set_s(std::string rx)
{
s = rx;
}
std::string get_s()
{
return s;
}
}
Now when I use the above method as in the following code
void main()
{
shared_cls r = SomeMethod("IBM",12);
//Here r does not have a valid string s
//However it does have a valid int i
}
Now my question is in the above main when I call the SomeMethod the r returned does not have a valid string s. It has a scrambled value I found this out by using a logger. However the value of s is totally find during the function SomeMethod. I resolved this issue by not returning the shared pointer by reference.In that case it works. Why does removing the reference make it work
Your shared_cls t goes out of scope because it is defined in the function SomeMethod itself. You need to return shared pointers by value if they are defined in the scope. In the link, it is explained why it is dangerous to return the reference of a temporary object.
In the case of std::string, string has a reference counting mechanism and when it's reference is decremented to zero, it becomes invalidated and a segmentation fault may be observed in such a case. Even if member int i is returned properly, it is still undefined behavior.
Related
I'm getting some strange error while running some C++ code that uses references. Basically I have three classes, the first contains an object of the second one while the second contains a vector of objects of the third class. This is the example code:
class MainClass {
public:
SecondaryClass myClass;
private:
void myFunction() {
int temp = 0;
const int& newValue = myClass.getFinalClassByIndex(temp).getInt();
// I add another FinalClass with the same value
myClass.addClassToVector(newValue);
// I try to add another one but the variabile "newValue" has another value
myClass.addClassToVector(newValue);
}
};
class SecondaryClass {
public:
SecondaryClass() {
myVector.push_back(FinalClass(0));
}
private:
std::vector<FinalClass> myVector;
void addClassToVector(const int& value) {
myVector.push_back(FinalClass(value));
}
FinalClass& getFinalClassByIndex(const int& index) {
return myVector.at(index);
}
};
class FinalClass {
public:
FinalClass(const int& value) : myInt(value){}
FinalClass(const int&& value) : myInt(value){}
const int& getInt(){ return myInt; }
private:
int myInt;
};
This is what happens when I run "myFunction": I get the integer value from the first object in the vector myVector and I put it in the newValue variable. Then I try to create two new FinalClass objects with the addClassToVector method, and these two will have the same integer value as the first one.
The first new object (that will be the second object in the vector) is created correctly; when I try to create the second object (the third one in the vector) the newValue variable does not have the value 0 as it should be, but it has a totally different one. It seems like the value has been moved instead of copied into the new class.
The second constructor in the class FinalClass is used when I create the class like ' FinalClass(0) ', it gives me an error if I don't use the "&&" notation.
What could the problem be in this case? I think it has something to do with the way I handle the references, but I don't understand why.
You return everything by reference. Which is fine until your vector needs to be resized, which reallocates your vector's memory and invalidates all references to that memory. Including your newValue reference. As a result your const int& newValue points to memory, which contains random data and it's a miracle your program doesn't crash at all.
Stop using references when you don't need them:
newValue = myClass.getFinalClassByIndex(temp).getInt();
and
int getInt(){ return myInt; }
even better:
auto getInt(){ return myInt; }
When I define a function of a class, I call another function of the same class within it. But when I do not type the class name it gives segmentation fault. Check below.
Header file
class DomainSolver
{
int fnc1 (UserDefinedType & var);
int fnc2 (UserDefinedType & var);
};
C file
int DomainSolver::fnc2 (UserDefinedType & var)
{
return 0;
}
int DomainSolver::fnc1 (UserDefinedType & var)
{
// fnc2 (var); // does not work
DomainSolver::fnc2(var); // works
return 0;
}
Wild guess… since the code you presented does not have any issues…
The function being called is declared virtual in a base class, so even if the virtual keyword is not present in the declaration here it is virtual.
The function being called does not access any member of the object.
You are calling the function on an invalid pointer or reference (for example through a null pointer or on an object that has already been deleted.
If all those guesses are right, the use of the qualification inhibits the dynamic dispatch mechanism, avoiding the dereference of an invalid pointer to the vtable. The code is still wrong (due to the third point above), but it seems to work.
The solution is not to call a member function through an invalid pointer or reference.
Although as pointed out by Zac's reply, the functions as you present them are not properly formed, there shouldn't be a difference between calling the scoped version; if you are getting a segfault in one case and not the other it's possibly because of code elsewhere.
Here is an example that works just fine:
dsolver.hh
#ifndef DSOLVER_HH
#define DSOLVER_HH
class DomainSolver
{
public:
int fnc1 (int& var);
int fnc2 (int& var);
};
#endif
dsolver.cc
#include <iostream>
#include "dsolver.hh"
int DomainSolver::fnc1 (int& var)
{
std::cout << "fnc1\n";
fnc2( var );
var = -1;
return var;
}
int DomainSolver::fnc2 (int& var)
{
std::cout << "fnc2\n";
var = 100;
return var;
}
main.cc
#include <iostream>
#include "dsolver.hh"
int main()
{
DomainSolver my_dsolver;
int my_int = 5;
my_dsolver.fnc1(my_int);
return 0;
}
Assuming this is close to your actual code, you have undefined behavior in fnc1:
int DomainSolver::fnc1 (UserDefinedType & var)
{
// fnc2 (var); // does not work
DomainSolver::fnc2(var); // works
// missing return!!!
}
You declare it to return an int, but then never return anything (in either case). Both cases are UB, so anything they do is technically "valid", since your code is not.
This code should be:
int DomainSolver::fnc1 (UserDefinedType & var)
{
return fnc2 (var);
}
As a side note: This is a good example of why you should never ignore the warnings given by the compiler (as you should have received a warning with both versions).
EDIT
With your latest edit adding a return value to fnc1, you'll need to show more of your actual code as there is not enough there to properly diagnose the problem (with the return being there, there is nothing wrong with your shown code).
Alright, so I have looked around online and clearly my problem is that I'm using a variable "val" here that stops existing when the function closes. Unfortunately, I haven't really found any actual solutions to my problem here. I'm sure this is an easy enough problem to solve once you know how, but I just don't have the knowledge.
In this code, just notice I'm trying to return an unsigned int val. I can't do that because the code wants a reference, not just a variable. I can't simply return val but I don't know what to do.
http://i.imgur.com/E8sf2aS.png
Thanks for the help.
Edit: sorry, I had some problems with the image, apparently I need to work on my rep.
I'm going to take a wild guess.
Foo& doStuff()
{
// blah blah
Foo val;
// ...
return val;
// val is no longer valid end of scope. Returning invalid reference.
}
Either pass in the result Foo instance to doStuff, or create a new Foo on the heap and return as pointer.
So,
void doStuff(Foo& val)
{
// blah blah
// ...
val = x;
}
or
Foo* doStuff()
{
// blah blah
Foo* val = new Foo; // dont forget to delete
// ...
return val;
}
Of course, you can return by value:
Foo doStuff()
{
// blah blah
Foo val;
// ...
return val;
}
Depending on how heavy a Foo is. Of course, since in this case a Foo is just an small int, you should simply return by value. For some cases of return by value for large/non-trivial types, a temporary copy is created (In those instances where there is no copy elision via RVO or NRVO); in these cases you might want to avoid returning large object types by value.
This code has a lot of problems, apart from being given in an image (!!!)
I guess you're trying to find the element at position pos-1 in a list, or something. The main problem referring to your question seems to be that you're first assigning val by value, then you have no reference to return. You should return n2->value directly, which should be a reference to unsigned int, like that:
const unsigned int &list::operator[](unsigned int pos) const
{
node *n1 = ???, *n2 = ???;
for (unsigned int k = 0; k < _size; k++)
{
if (k == pos)
return n2->value;
n1 = n2->next;
n2 = n1;
}
return ???;
}
Other problems remain, e.g.
why you need two node* and not just one (looking for position pos-1 directly)
how to initialize n1, n2 (somehow pointing to the head of your list; obviously new node() should not work)
what to return if input argument pos is out of range (possibly return a reference to some static variable that you can detect, or throw an exception)
For these problems, more context would be needed from your side.
Reference variables, are only valid if the object to which "refer" to, exists in memory. Passing around references to an out of scope variable, is considered undefined behavior.
This is the mistake in your code.Please correct it.
const unsigned int& list::operator[] (unsigned int pos)const
{
const unsigned int val = 0;
return val; //this is a local variable, whose scope ends here, a reference to this should not be returned
}
This is the compiler's warning, to your code.
warning: reference to local variable ‘val’ returned [enabled by default]
Please listen to compiler warnings (especially c/c++ !!), in your case simply using pass by value, would have been sufficient.
Edit:
In case the return variable, is enforced to be a reference type, and cannot be avoided, you can then extend the life of you local variable, to throughout the existence of the program by making it static.
const unsigned int& list::operator[] (unsigned int pos)const
{
static const unsigned int val = 0;
return val;
}
Th variable val is now a static local variable, whose life is throughout the program,
so pasing around references to this variable should be OK, but not recommended programming,
since a pass by value will suffice for the needs of your application.
Can anyone tell me whether this is safe and defined:
class RefClass
{
public:
RefClass(int i) { this->i = i; }
int& GetRef() { return i; }
private:
int i;
};
RefClass rc(10);
int* refp;
{
refp = &rc.GetRef();
}
*refp = 20;
Specifically I am concerned with the lifetime of the returned reference in the nested scope and whether it can be referenced in that scope and then later dereferenced as an lvalue after that scope has dissolved.
This code compiles and runs as expected in VS2012, but that doesn't mean it will in the next version, so I am trying to find a definitive answer.
Yes, that's fine.
The returned reference is a temporary, lasting until the end of the statement containing the function call. It's used within its lifetime to set refp to point to its target, rc.i. It's not needed to dereference the pointer after that.
The only danger is if the object might be destroyed, leaving the pointer dangling:
int* refp;
{
RefClass rc(10);
refp = &rc.GetRef();
} // rc is destroyed here
*refp = 20; // BOOM!!!
Yep, this is all right. You'd have issues in the following case:
int* refp;
{
RefClass rc(10);
refp = &rc.GetRef();
}
*refp = 20;
I am running the following piece of code under the Marmalade SDK. I need to know if there's a "bug" in my code or in Marmalade:
template <class Return = void, class Param = void*>
class IFunction {
private:
static unsigned int counterId;
protected:
unsigned int id;
public:
//
static unsigned int getNewId() { return counterId++; }
template <class FunctionPointer>
static unsigned int discoverId(FunctionPointer funcPtr) {
typedef std::pair<FunctionPointer, unsigned int> FP_ID;
typedef std::vector<FP_ID> FPIDArray;
static FPIDArray siblingFunctions; // <- NOTE THIS
typename FPIDArray::iterator it = siblingFunctions.begin();
while (it != siblingFunctions.end()) {
if (funcPtr == it->first) return it->second; /// found
++it;
}
/// not found
unsigned int newId = getNewId();
siblingFunctions.push_back( FP_ID(funcPtr, newId) ); // <- NOTE THIS
return newId;
}
//
virtual ~IFunction() {}
bool operator<(const IFunction* _other) const {
if (this->id < _other->id) return true;
return false;
}
virtual Return call(Param) = 0;
};
Note that every time template class discoverId is called for the 1st time, a static local array is created.
At program exit, the Marmalade memory manager complains that the memory reserved at this line :
siblingFunctions.push_back( FP_ID(funcPtr, newId) );
hasn't been freed. (The truth is that I don't empty the array, but how could I, I don't have access to it outside that function!).
Here is the catch : Marmalade complains only for the memory reserved at the very first call of this function! This function is called several times and with several different template parameters, but the complaining always occurs only for the memory reserved at the 1st call. This is the case even if I mix up the order of the various calls to this function. Memory reserved for every call after the 1st one is automatically freed - I have checked this out.
So, who's to blame now?
I don't know what "Marmalade" is (and a quick search for this word expectedly found a lot of irrelevant references) but your code doesn't have a resource leak with respect to the static FPIDArray siblingFunctions: this object is constructed the first time the function is called. It is destroyed at some point after main() is exited. I seem to recall that the order of destruction of objects with static linkage is the reverse of order in which objects are constructed but I'm not sure if this extends function local statics.