1

It works when, in the loop, I set every element to 0 or to entry_count-1. It works when I set it up so that entry_count is small, and I write it by hand instead of by loop (sorted_order[0] = 0; sorted_order[1] = 1; ... etc).

Please do not tell me what to do to fix my code. I will not be using smart pointers or vectors for very specific reasons. Instead focus on the question: What sort of conditions can cause this segfault? Thank you.

---- OLD -----

I am trying to debug code that isn't working on a unix machine. The gist of the code is:

int *sorted_array = (int*)memory;
// I know that this block is large enough
// It is allocated by malloc earlier

for (int i = 0; i < entry_count; ++i){
  sorted_array[i] = i;
}

There appears to be a segfault somewhere in the loop. Switching to debug mode, unfortunately, makes the segfault stop. Using cout debugging I found that it must be in the loop.

Next I wanted to know how far into the loop the segfault happend so I added:

std::cout << i << '\n';

It showed the entire range it was suppose to be looping over and there was no segfault.

With a little more experimentation I eventually created a string stream before the loop and write an empty string into it for each iteration of the loop and there is no segfault.

I tried some other assorted operations trying to figure out what is going on. I tried setting a variable j = i; and stuff like that, but I haven't found anything that works.

Running valgrind the only information I got on the segfault was that it was a "General Protection Fault" and something about default response to 11. It also mentions that there's a Conditional jump or move depends on uninitialized value(s), but looking at the code I can't figure out how that's possible.

What can this be? I am out of ideas to explore.

  • 1
    What does the debugger tell you? How do you know the block is large enough? How was it allocated? Could `entry_count` have changed since then? Why aren't you using `std::vector`? – Mike Seymour Mar 29 '15 at 02:00
  • 1
    We need to see more code. Assuming `int* memory = new int[entry_count]`, then everything should be OK. Or, load the `core` file in gdb and show us the output of `where` and `bt full`. Finally, you should use `new` or better, `std::vector`. – jww Mar 29 '15 at 02:06
  • 1
    Nothing in the code you provided should give a segfault, if your assumptions about `memory` are correct. I suggest using `std::vector` which will be bounds checked on good debug compilers and probably show your problem immediately. – Neil Kirk Mar 29 '15 at 02:07
  • @MikeSeymour Is there ever a reason to use raw pointers to store an array? – The Vivandiere Mar 29 '15 at 02:07
  • @Golazo If you were writing a low-level memory management system. – Neil Kirk Mar 29 '15 at 02:08
  • @NeilKirk Does low-level imply only C, and not C++, and hence `std::vector` not being available? – The Vivandiere Mar 29 '15 at 02:09
  • 1
    @Golazo No, as C++ and C are different languages and this question is about C++. – Neil Kirk Mar 29 '15 at 02:09
  • The first step is to take statements like _"I know that this block is large enough"_ and throw them away. – Lightness Races in Orbit Mar 29 '15 at 02:13
  • The same exact code works under windows. I know that it is big enough because with the exact same values in the variables used in calls to allocation, I looked at the memory in Visual Studio, and it fits. –  Mar 29 '15 at 02:14
  • You may have undefined behavior in some other code, causing it to occur in this code. – Neil Kirk Mar 29 '15 at 02:21
  • Rolled back; it's rough being wrong, but there's no reason to be mad at the people you're asking for help. – Carl Norum Mar 29 '15 at 02:32
  • @4th_dimention `The same exact code works under windows.` Which means absolutely nothing in the world of C++. You have memory corruption, there is no guarantee how your program will run. – PaulMcKenzie Mar 29 '15 at 02:40
  • I understand that. The point is that I know that under this test case the block of memory is large enough. Unless the Unix allocator likes to get less memory than you ask for. –  Mar 29 '15 at 02:44
  • You've corrupted memory, period. Once that happens, throw all of your expectations out the window. – PaulMcKenzie Mar 29 '15 at 02:47
  • Okay, in that case what typically causes memory corruption on Unix that does not cause memory corruption on windows? –  Mar 29 '15 at 02:48
  • C++ has a condition called `undefined behavior`. This means when you corrupt memory *anything may happen*. There is no answer to your question except that you wrote bad code, and undefined behavior kicked in. You can write a buggy program for Windows that may or may not run on the same machine. – PaulMcKenzie Mar 29 '15 at 02:50
  • In practice, what tends to work on the cl compiler that would not work on g++ 4.8 that can cause a General Protection Fault? –  Mar 29 '15 at 02:52
  • There is no "tends to work". It either is valid code or it isn't. If it isn't, then all bets are off. – PaulMcKenzie Mar 29 '15 at 02:54
  • Then explain to me why the same thing happens with every run? I know in theory land "anything CAN happen" but in the real world there really is one specific thing that does happen. So if you do know, then share, otherwise, you just don't know. –  Mar 29 '15 at 02:56
  • Change compiler options and then what will the explanation be if your Windows version suddenly crashes? Trying to explain undefined behavior will be equivalent to a dog chasing its tail. – PaulMcKenzie Mar 29 '15 at 02:58
  • The point is I am trying to find the problem, and it would be nice to know what I am looking for. I don't know much about Unix, thus I am asking if anyone can tell me what I am looking for. –  Mar 29 '15 at 03:01
  • This is the reason why others mentioned to you about smart pointers, vectors, etc. There is a point where it becomes difficult, if not near impossible to pinpoint where the code fails at runtime. There can be an umpteen reasons for a program to fail -- mismanagement of pointers, dynamic memory, or just plain wrong C++ programming that just happens to not fail all the time (returning pointers to local variables, for example). – PaulMcKenzie Mar 29 '15 at 03:07

4 Answers4

5

This is clearly a symptoms of invalid memory uses within your program.This would be bit difficult to find by looking out your code snippet as it is most likely be the side effect of something else bad which has already happened.

However as you have mentioned in your question that you are able to attach your program using Valgrind. as it is reproducible. So you may want to attach your program(a.out).

$ valgrind --tool=memcheck --db-attach=yes ./a.out

This way Valgrind would attach your program in the debugger when your first memory error is detected so that you can do live debugging(GDB). This should be the best possible way to understand and resolve your problem.

Once you are able to figure it out your first error, fix it and rerun it and see what are other errors you are getting.This steps should be done till no error is getting reported by Valgrind.

However you should avoid using the raw pointers in modern C++ programs and start using std::vector std::unique_ptr as suggested by others as well.

Mantosh Kumar
  • 5,659
  • 3
  • 24
  • 48
2

Valgrind and GDB are very useful.

The most previous one that I used was GDB- I like it because it showed me the exact line number that the Segmentation Fault was on.

Here are some resources that can guide you on using GDB:

GDB Tutorial 1

GDB Tutorial 2

If you still cannot figure out how to use GDB with these tutorials, there are tons on Google! Just search debugging Segmentation Faults with GDB!

Good luck :)

Tman
  • 136
  • 8
0

That is hard, I used valgrind tools to debug seg-faults and it usually pointed to violations.

Likely your problem is freed memory that you are writing to i.e. sorted_array gets out of scope or gets freed. Adding more code hides this problem as data allocation shifts around.

iceraj
  • 359
  • 1
  • 5
  • Did you use memgrind with bounds check? Memcheck Memcheck detects memory-management problems, and is aimed primarily at C and C++ programs. When a program is run under Memcheck's supervision, all reads and writes of memory are checked, and calls to malloc/new/free/delete are intercepted. As a result, Memcheck can detect if your program ... – iceraj Mar 29 '15 at 02:10
  • I have never heard of that. I used memcheck that was the only option I set. –  Mar 29 '15 at 02:11
  • There are a lot of options [Memcheck: a memory error detector](http://valgrind.org/docs/manual/mc-manual.html#mc-manual.errormsgs). I found --malloc-fill and --free-fill useful. Also, if you can post mc report that would help. – iceraj Mar 29 '15 at 02:25
0

After a few days of experimentation, I figured out what was really going on.

For some reason the machine segfaults on unaligned access. That is, the integers I was writing were not being written to memory boundaries that were multiples of four bytes. Before the loop I computed the offset and shifted the array up that much:

int offset = (4 - (uintptr_t)(memory) % 4) % 4;
memory += offset;

After doing this everything behaved as expected again.