Segmentation violation?

Started by
14 comments, last by suliman 7 years ago

Hi

Im trying to submit an assignment in c++ that gives me this error message (see below). It compiles and runs fine on my own machine (and when I debug I find nothing strange) but the server compiler (which I cannot debug) does not accept it and "crashes" with this message. It runs fine for me both in debug and release builds. What could be the problem and how could I find it? Can I disable something (visual studio 2008) that makes it less accepting so it becomes more "sensitive"? The server compiler seems to be very sensitive...

Thanks for your input!

Erik

-------------- error message -----------------

Signal 11 is SIGSEGV, Segmentation Violation. This means that your program has tried to access memory which it was not allowed to access, either because the memory was not mapped by the process or due to permission errors. Make sure everything is properly initialized, be careful with your pointer arithmetic and don't follow null pointers.

Advertisement

Sounds like problem is on your side. It's runtime issue, so you can't make it detectable with compiler options. Something in your code breaks on unexpected data. It might be uninitialized variables like the message suggests, or bug in logic, when you read/write memory beyond allocated areas, or dereferencing null pointer.

Either review your code carefully, or run it under Valgrind in virtual pc with linux installed. With valgrind you will know exact spot of crash, or track garbage data in pointers down to the point where it was created.

DrMemory might be a decent alternative to valgrind to avoid the need to run on a linux VM.

You might also find memory issues by using _CrtCheckMemory or _CRTDBG_CHECK_ALWAYS_DF: See https://msdn.microsoft.com/en-us/library/974tc9t1.aspx


1) It compiles and runs fine on my own machine (and when I debug I find nothing strange) but the server compiler (which I cannot debug) does not accept it and "crashes" with this message. It runs fine for me both in debug and release builds.

2) What could be the problem and how could I find it?

3) Can I disable something (visual studio 2008) that makes it less accepting so it becomes more "sensitive"?

1)

Segfaults have little to do with compilation. Segfaults mean the running program touched memory it should not have, like following a null pointer, following an unintialized pointer, accessing outside of an array's bounds, or similar.

If you are submitting the code and it is generating a segfault, such as submitting it to a school's automatic grading program, then the segfault is probably a bug in the tool that manages their compiler.

Otherwise, the fault would be with your own program touching memory it should not have.

2)

The problem is that some program in the process is touching memory it should not have. Without more information it is hard to tell if that is your program crashing when being run, or if it is the server you submit the code to that has its code crashing.

3)

No. It is not a setting on your compiler. Depending on the nature of the bug you might be able to detect it with different settings, maybe the compiler could generate a warning about using an uninitialized value, or using a pointer after releasing it, or some other detection where the code might touch memory it should not. You can try adjusting the warning level settings on the compiler, but that will only help you find the error, not fix it.

The best way to find it is to attach the program to a debugger. When it dies the debugger will capture the fault, stop execution, and show you the exact location and program state at the time of the crash.

Is it possible your school server is testing your program with different inputs than you are? You should probably check all the edge conditions your program could possibly encounter. Those TAs that write the grading test suites are sneaky beggars looking to break your program, and they have nothing on the real world waiting to eat your code alive when it its the wild.

It pays to be a paranoid programmer.

Stephen M. Webb
Professional Free Software Developer

If it works fine in your environment but not in a different environment, then there is probably something in your code that doesn't account for different environments. Consider things that might go wrong in different environments, such as assuming that a file is in a certain location, or that certain directories or drives exist. Better examples are hard to give without knowing what the program does.

If you print a message to the console, can you see that output? If so, you can sprinkle your code with progress messages (e.g. "entered function foo", " about to access array element 42"). You may need to flush the output too.

If not (perhaps only the segfault will be reported regardless), then try commenting out some code and re-submitting. You should be able to narrow down the affected area by successively commenting out different sections (you might need to put in safe "dummy" code to keep it compiling, e.g. returning 0 rather than summing an array).

I've tried drmemory (no problem) debugged through the code with many examples of different map sizes etc to no avail! All seem to work fine for me.

Could someone do me a HUGE favour and look at the actual code? It's not super long but I know im still asking alot. I just dont find the problem :(

https://www.dropbox.com/s/o8kroh9q2dkci56/pathfind_astar.zip?dl=0

(5kb zipfile, also with main.cpp to show usage and speed up testing)

What does the stackdump say? Usually a crash like this can be precisly pinpointed to the spot where it breaks. Often that gives sufficient clues to what is not doing its job.

The simplest way to get a stackdump is to run the code under a debugger. When it crashes, the debugger grabs it, and shows you where exactly it crashes [1], with a dump with all function-calls in-progress from 'main()' to the line where it dies (ie all functions on the stack, which is how it got its name).

[1] Usually, you need to compile the code with debugging symbols enabled to get useful names and line numbers.

Edit: Never mind, I now read you cannot go this route.

I took a quick look, and it seems pretty good, compiling and running didn't crash.

valgrind says all memory is properly released, and found no other errors either.

Perhaps there is something special about the server, eg 64K memory model, or otherwise limited time or space? Perhaps wrong c++ version?

I won't hunt down the segfault, since this is an assignment, but I will explain a couple of standard C++ tools and patterns that are quite likely to solve this problem if the error is indeed referring to a segfault being emitted by your own program and not the build tool.
I see a lot of pointers around the place, and some of them are even being re-used (which is not kosher unless you really like your debugger). Most of these pointers are being used to store collections of data:


	int *closedMap = new int[nMapWidth*nMapHeight]; // closed nodes have been checked
	int *openMap = new int[nMapWidth*nMapHeight]; // open nodes have not been checked
	int *dirMap = new int[nMapWidth*nMapHeight];

Let's make life far more simple:


        //#include <vector>
        size_t mapSize = nMapWidth * nMapHeight;
	std::vector<int> closedMap(mapSize, 0); // closed nodes have been checked
	std::vector<int> openMap(mapSize, 0); // open nodes have not been checked
	std::vector<int> dirMap(mapSize);

This allocates three vectors of int with size 'mapSize'. The open and closed lists have their values initialized to zero.
Vectors elements can be accessed like arrays:


dirMap[10];

Vectors are aware of their own length:


dirMap.size();

The will throw a specific exception if you attempt out-of-bounds access, which will make the bug easier to find if that's what's happening. Vectors also do not require deletion. When the object goes out of scope it will automatically be destroyed and destruct all of its elements.
Vector can also resize itself dynamically:


std::vector<int> foo; //starts at zero length
int bar = 42;
foo.push_back(bar); //automagically increases its size to store new elements
foo.push_back(bar);
foo.push_back(bar);


In addition to preferring vectors over manually allocated arrays, I'm looking at the function prototype for FindPath(), and you could do something like this:


struct Position { int x, y; }; //suggestion
struct Dimensions { int width, height; }; //suggestion

// v Return the path as a vector                                                 v use a vector for the map - pass it in by const reference
std::vector<int> FindPath(const Position start, const Position target, const std::vector<unsigned char>& map, const Dimensions mapSize);

You can store the map in a vector and pass it in to the function as a const reference (if you don't know what that means please ask), which would give you bounds checking when accessing map cells.
More importantly, you can return your path as a vector. The vector will know its own size and doesn't require any voodoo to be returned. If no path is found you can simply return an empty vector. One of the added benefits of this is that you don't have to specify a limit on the path length, since the vector holding the result can be any size.
Also, if you have a 'Position' struct, you could return a std::vector<Position> instead of returning one-dimensional indices.

So that's vector. (more info http://en.cppreference.com/w/cpp/container/vector)

Another thing I saw was this:


n=new simplePatherNode(nStartX, nStartY, 0, 0); //with sizeof(simplePatherNode) == 4 * sizeof(int)

Point-blank do this instead:


simplePatherNode n(nStartX, nStartY, 0, 0);

Manual memory management is highly error prone. In C++ we try to avoid it wherever possible. 4 integers is absolutely trivial and can fit on the stack with no issues. Don't dynamically allocate something just because it's a custom type.

Those two changes can take all the raw pointers out of your code, which will make segfaulting significantly more difficult.

Some other advice just from browsing the code:

  • You can avoid the braces around one-line bodies, like you do with the for-loop in main(). It's better not to do this though, as it lacks visual distinction that makes the code easier to read and it's been found to be error prone.
  • You don't have to return anything from main() in C++. The compiler will assume zero.
  • You specify that the map is 4x3, but the array storing the map is linear. How about this?
    
      unsigned char pMap[] = { //const std::vector<unsigned char> map = {
        1, 1, 1, 1,
        0, 1, 0, 1,
        0, 1, 1, 1
      };
  • 
    static simplePatherNode* n; // the current node
    static simplePatherNode* n2; // the "child" node, bordering n
    
    vs
    
    //do not use 'static' here - the static queue may well be causing your bug
    simplePatherNode* curNode;
    simplePatherNode* childNode;
    //but do use clear names
    
    https://www.google.com/search?q=premature+optimization+is+the+root+of+all+evil
  • Speaking of that queue, I see you manually emptying it in a couple places by popping until it's empty. This is understandable since pqueue lacks a clear() function, but there's a more concise way to do this in case you ever need it:
    
    std::priority_queue<int> foo;
    foo = std::priority_queue<int>(); //just replace it with a new queue
    
  • That's probably enough for now. Please keep us updated on your progress.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement