C++ segmentation fault when trying to output object functions - c++

I am attempting to output functions common to a set of objects that share a base class and I am having some difficulty. When the objects are instantiated they are stored in an array and then I am attempting with the following code to execute functionality common to all the objects in this loop:
if ( truck <= v ) // all types of trucks
vptr is an array of objects and the functions in the loop are common to all the objects. The code compiles fine but when I run it I get a segmentation fault when it enters this loop. I'm fairly confident that the call to the first function in this loop is what is causing the problem.
this is how I have instantiated the objects in a previous loop:
vptr[ i ] = new Vehicle( sn, pc );
I should also mention, I'm sorry I forgot to be clear from the beginning, that in this array each object is of a different class. They all share a base class but they are derived objects of that class. Sorry for forgetting that probably important piece of information.
thanks
nmr

dynamic_cast to a pointer type returns a null pointer (aka 0, NULL) if the object isn't of the specified type. You must check the pointer before using it, or use a reference type (which throws an exception on failure instead):
if (Truck* p = dyanmic_cast<Truck*>(vptr[i])) {
// use the pointer here
}
else {
// vptr[i] doesn't point to a Truck
}
(Notice the nice effect of the correctly-typed pointer being scoped for you, take advantage of this when you can to improve readability.)

If you use a debugger, you can easily figure out which call is causing the segmentation fault and even examine memory to see if you have a null pointer, etc.
GCC with GDB is a good example. Try this--first build your application with debugging info (to do this you add the -g switch to your compiler):
gcc -g test.c -o myProgramName
Now launch GDB:
gdb myProgramName
At the first GDB prompt, enter the 'r' command to run the program:
(gdb) r
Then, when you reach the segfault, use the 'bt' command to view the stack trace and find out where the program was when it had the bad memory access:
Program received signal SIGSEGV, Segmentation fault.
0x08048380 in testFunction2 () at test.c:17
17 *test = 1;
(gdb) bt
#0 0x08048380 in testFunction2 () at test.c:17
#1 0x0804836e in testFunction1 () at test.c:10
#2 0x0804835a in main () at test.c:5
When you compile with debugging enabled, it lets you see the source file, line number, and the actual code that caused the crash. Learning to use a debugger makes hunting down segmentation faults really easy.
Debuggers also let you examine memory--with the above example, I can check the value of the 'test' pointer:
(gdb) print test
$1 = 0x0
Whoops, the pointer was NULL when I tried to change the memory it referenced, thus I was accessing memory my program wasn't allowed to touch, causing a segmentation fault.
Try the 'print' command with objects as well--GDB is smart enough to actually break the object down and show you the value of each of the object's members. Additionally, you can use the 'printf' command to print strings, etc. while you're debugging your program.
Hope this is helpful,
Maha

Related

Segmentation fault debugger error message meaning?

I am learning c++ and I have a segmentation fault with my code. I ran the debugger and I got the following error message which I am struggling to understand.
Program received signal SIGSEGV, Segmentation fault. 0x0000000008002e3e in std::__uniq_ptr_impl<TreeNode<int>, std::default_delete<TreeNode<int> > >::_M_ptr (this=0x8) at /usr/include/c++/7/bits/unique_ptr.h:147
147 pointer _M_ptr() const { return std::get<0>(_M_t); }
Does this mean the segmentation fault is occurring in line 147 in my TreeNode class? If so, the line 147 is empty.
Can someone please clarify.
Edit: after following #HolyBlackCats advice I typed in bt and got the following message.
#0 0x0000000008002e3e in std::__uniq_ptr_impl<TreeNode<int>, std::default_delete<TreeNode<int> > >::_M_ptr (this=0x8) at /usr/include/c++/7/bits/unique_ptr.h:147
#1 0x0000000008002680 in std::unique_ptr<TreeNode<int>, std::default_delete<TreeNode<int> > >::get (this=0x8) at /usr/include/c++/7/bits/unique_ptr.h:337
#2 0x0000000008001c55 in BinarySearchTree<int>::begin (this=0x7ffffffedf48) at tree.h:99
#3 0x0000000008000d98 in main () at TestTreeD.cpp:20
I still do not understand what this means.
As the error message states, the segfault occurred when executing code compiled from line 147 of the C++ library header file.
The backtrace shows the execution stack at the point where backtrace occurs.
A backtrace does not always give you a full explanation for the reasons for your segfault. Unfortunately, C++ is not that easy. The backtrace only gives you the starting clues for investigating the reason for the crash. A backtrace is only the starting point for our debugging. Where you go from there depends on what you know and your experience.
Sometimes even the backtrace itself is garbage, because the stack was corrupted.
And at other times the backtrace will be good, but not have anything to tell you about the reason for the segfault, but it will tell you the how you wound up in that part of the code. So, for example, you would use this information to set a breakpoint earlier in the code, before the crash, and when execution stops there, you can analyze and inspect the values of all objects and variables, and see if anything seems out of place, or if there's something wrong. What's "something wrong" means is going to be entirely up to you to determine, based on the exact details of your application.
I could find only one clue that's apparent by inspecting your shown backtrace, that would be stack frame #1:
#1 0x0000000008002680 in std::unique_ptr<TreeNode<int>,
std::default_delete<TreeNode<int> > >::get (this=0x8)
==========
According to this backtrace, the code is executing an object at memory address 0x8. This is, obviously, complete nonsense. It's quite common to see this of 0x0, a.k.a. a null pointer, when picking up the flaming wreckage of a backtrace. 0x8 is close enough to indicate memory corruption. Probably some object that has a unique_ptr as a class member, the pointer to this object is null, and the code is attempting to invoke a method of the unique_ptr, which is at offset 0x8 in the class that contains it.
So, at this point, the shown code most likely used a garbage pointer, or an uninitialized reference, or some other logical error to invoke a method through a bad pointer or reference.
Your next step would be to set a breakpoint wherever stack frame #2 is, that invoked some operation on some bogus unique_ptr it got somewhere. Based on what you see there, you will either find more clues, or, after inspecting the surrounding code, be able to determine the underlying bug.
Good luck.
I would like to point out that this occurs if one is trying to initialize a static const-member through moving an initialized instance of std::unique_ptr into the uninitialized member, which will cause such behaviour.
Here an example of what I mean:
class SomeClass
{
private:
static const std::unique_ptr<string> RESOURCE;
public:
SomeClass() = default;
~SomeClass() {};
private:
static std::unique_ptr<string>&& initResource()
{ return std::unique_ptr<string>(new string{"fdsa"}); }
};
const std::unique_ptr<string> SomeClass::RESOURCE = SomeClass::initResource();
int main(int argc, char const* argv[])
{
return 0;
}
Try compiling this code with the debug-flag (with g++ it's the -g-flag) and run it using gdb, and you will see quite the similar behaviour as one may observe below:
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555638 in std::__uniq_ptr_impl<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::default_delete<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_ptr (this=0x0) at /usr/include/c++/7/bits/unique_ptr.h:147
147 pointer _M_ptr() const { return std::get<0>(_M_t); }
Basically in order to fix this, simply remove the rvalue reference (<type>&&) from methods like SomeClass::initResource() and/or do not use things that enforce a moving operation such as std::move() in those situations where initialization is supposed to happen.

Is it possible that a program sends a Segfault whenever an object tries to access one of its attributes?

I have a class with a bool attribute called global.
I have a segmentation fault happening when calling one of its methods from the outside.
Basically, I call this method. This method internally calls another method, which calls another method and so on (this is because each method does something slightly more complex).
At the end of the method calling chain there's a method which checks the attribute global, and does different things based on its content.
Using gdb I found out the segmentation fault error is generated at the exact line if (global) { in this last method. I tried moving this condition check higher in the method call chain (so that the condition is checked before continuing deeper in the method chain), but the result doesn't change (in other words, wherever it is placed, if (global) { always causes a segmentation fault`).
Is it possible that checking for the attribute global causes a segmentation fault? What could this mean? What causes this?
I am compiling usin g++ -std=c++11 -Wall -Wextra -pedantic -g.
A segmentation fault (SIGSEGV) means that your program has attempted to access memory outside its address space.
This is typically caused by dereferencing uninitialized pointers or pointers to objects which lifetime has ended, reading off the end of the stack or similar.

Segmentation fault on one Linux machine but not another with C++ code

I have been having a peculiar problem. I have developed a C++ program on a Linux cluster at work. I have tried to use it home on an Ubuntu 14.04 machine, but the program, which is composed of 6 files: main.hpp,main.cpp (dependent on) sarsa.hpp,sarsa.cpp (class Sarsa) (dependent on) wec.hpp,wec.cpp, does compile, but when I run it it either returns segmenation fault or does not enter one fundamental function of the class Sarsa.
The main code calls the constructor and setter functions without problems:
Sarsa run;
run.setVectorSize(memory,3,tilings,1000);
etc.
However, it cannot run the public function episode , since learningRate, which should contain a large integer, returns 0 for all episodes (iterations).
learningRate[episode]=run.episode(numSteps,graph);}
I tried to debug the code with gdb, which has returned:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000408f4a in main () at main.cpp:152
152 learningRate[episode]=run.episode(numSteps,graph);}
I also tried valgrind, which returned:
==10321== Uninitialised value was created by a stack allocation
==10321== at 0x408CAD: main (main.cpp:112)
But no memory leakage issues.
I was wondering if there was a setting to try to debug the external file sarsa.cpp, since I think that class is likely to be the culpript
In the file, I use C++v11 language (I would be expecting errors at compile-time,though), so I even compiled with g++ -std=c++0x, but there were no improvements.
Unluckily, because of the size of the code, I cannot post it here. I would really appreciate any help with this problem. Am I missing anything obvious? Could you help me at least with the debugging?
Thank you in advance for the help.
Correction:
main.cpp:
Definition of the global array:
`#define numEpisodes 10
int learningRate[numEpisodes];`
Towards the end of the main function:
for (int episode; episode<numEpisodes; episode++) {
if (episode==(numEpisodes-1)) { // Save the simulation data only at the
graph=true;} // last episode
learningRate[episode]=run.episode(numSteps,graph);}
As the code you just added to the question reveals, the problem arises because you did not initialize the episode variable. The behavior of any code that uses its value before you assign one is undefined, so it is entirely reasonable that the program behaves differently in one environment than in another.
A segmentation fault indicates an invalid memory access. Usually this means that somewhere, you're reading or writing past the end of an array, or through an invalid pointer, or through an object that has already been freed. You don't necessarily get the segmentation fault at the point where the bug occurs; for instance, you could write past the end of an array onto heap metadata, which causes a crash later on when you try to allocate or release an unrelated object. So it's perfectly reasonable for a program to appear to work on one system but crash on another.
In this case, I'd start by looking at learningRate[episode]. What is the value of episode? Is it within the bounds of learningRate?
I was wondering if there was a setting to try to debug the external file sarsa.cpp, since I think that class is likely to be the culpript
It's possible to set breakpoints in functions other than main.cpp.
break location
Set a breakpoint at the given location, which can specify a function name, a line number, or an address of an instruction.
At least, I think that's your question. You'll also need to know how to step into functions.
More importantly, you need to learn what your tools are trying to tell you. A segfault is the operating system's reaction to an attempt to dereference memory that doesn't belong to you. One common reason for that is trying to dereference NULL. Another would be trying to dereference a pointer that was never initialized. The Valgrind error message suggests that you may have an unitialized pointer.
Without the code, I can't tell you why the pointer isn't initialized when you run the program on your home system, but is (apparently) initialized when you run it at work. I suspect that you don't have the necessary data on your home system, but you'll need to investigate and figure that out. The fundamental question to keep asking yourself is "what is different between my home computer an dmy work computer?"

gdb interpret memory address as an object

I am investigating a crash, based on the available core dump. The application crashing is a C++ program, built with gcc and running on RH5. The backtrace seems valid till the #1 frame. There trying to print an object I get
<invalid address>, <error reading variable>
Since I have the address of the object from the #2 frame is it a valid presumption that I can somehow 'dump' the memory in which the object is allocated and still collect some info. Furthermore, instead of trying to guess how the object is aligned, can I force gdb to print the address as if it is an object, even though it detects some error. My idea is that maybe the object has already been deleted, but just maybe the memory is still there and I can print some member variable.
Please comment on is that possible, and if so, how it should be done in gdb terms. 10x.
Well, if you have an address you can always do:
print *(class MyClass*)pointer_var

gdb detected a segmentation fault. How to pinpoint the exact source?

(gdb) s
Things:action (this=0x7fffffffdce0, packet=0x62c980) at file:41
41 if( thing->work(data) ) {
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x00000000004040e1 in Things:action (this=0x7fffffffdce0, packet=0x62c980) at file:41
41 if( thing->work(data) ) {
In a backtrace, call to work(data) is a last one; and the segmentation happened (as it seems) before the GDB-managed process entered work(data). In a list, there is no declaration of work(data), so guessing that more code was executed, than is shown by backtrace and latest step.
Can that segfault come from the bad pointer being passed as a function argument in a bad manner (without "extern C", or some other preparations)? (assuming no function code was executed)
How to get a detailed trace to determine, was any work() code executed after entering the function, or the error happened right at the moment, when process tried to enter the function, thereby passing it's arguments to libc?
As I said in the comment : I believe that the execution never reached work(data) because the this pointer is invalid (0x7fffffffdce0 looks like garbage). The SIGSEGV is on this->.
Has the object been destroyed / deleted at some point, and have you kept a reference or pointer to it ?
Well, work() can't have been started unless it's inline, or you it would have been on the top of the backtrace...
I would try disassembling to see what instruction triggered the SIGSEGV and go from there.