[m-users.] seg fault, 64 bit

Paul Bone paul at bone.id.au
Sat Jun 8 08:57:07 AEST 2013


On Fri, Jun 07, 2013 at 08:38:55PM +0200, Tomas By wrote:
> Hi all,
> 
> I am getting this error on Ubuntu 64 bit, with Mercury 13.05:
> 
> | *** Mercury runtime: caught segmentation violation ***
> | cause: address not mapped to object
> | address involved: (nil)
> | This may have been caused by a stack overflow, due to unbounded recursion.
> | exiting from signal handler
> | Segmentation fault (core dumped)
> 
> with these settings:
> 
> | MERCURY_OPTIONS=--detstack-size 3000000 --nondetstack-size 3000000
> 
> and this amount of data (output of wc):
> 
> | 289358  1735415 33502285 total
> 
> Does this behaviour seem reasonable?
> 

Although you describe your data in your later e-mail, remember that stack
usage does not have to correlate with data size.  It is possible (and
easy) to create a very small program that exhausts the stack size.

> Any ideas about anything I can change?

I will assume that the segfault is definitely caused by a stack overflow,
there is no proof that this is the case.  However you say that running on a
single data file does not make the program crash, so it is a likely cause.

We have a stack segments grade that allows the runtime system to use a
dynamic amount of stack size.  Try compiling with the grade flag
--stack-segments or add .stseg to your low-level C grade string.  Note that
the high-level C grades always use C's stack (--(non)detstack-size will not
help).  This can be useful if you need just that tiny bit more stack size,
or if you want to avoid tuning or configuration when you distribute the
program.

Not all 'last calls' are tail cails.  Consider:

    map(_, [], []).
    map(P, [X | Xs], [Y | Ys]) :-
        P(X, Y),
        map(P, Xs, Ys).

Looks tail recursive right?  It's not.  The construction of [Y | Ys]
must occur after the recursive call to map.  (This is not true in
Prolog).  So it can be easy to write non tail recursive code.  This can be
fixed by using the Last Call Modulo Construction (LCMC) optimisation.  Try
enabling this optimisation (See the user guide).

To find out which recursions are very deep (but may or may not be tail
calls) try using the debugger.  Run your program until it crashes, look at
the last event number, run the program again stepping over this many minus
about 100 events and the program's state will be near the point at which it
crashed.  Then give the 'stack' command to see a list of stack frames.  The
stack command will show you recursive and mutually recursive parts of your
program, along with how deep the recursions are.

Some code such as the map example above, even if it's not tail recursive,
can be made to use less stack space with a simple transformation.  Take your
existing loop and make two nested loops.  Make the inner loop return after
so many iterations, say 100,000.  Then in the next iteration of the outer
loop call the inner loop again to work on some more of the input.


> 
> Is there another way to set the stack sizes? It seems that MCFLAGS in
> Mmake no longer works.

I thought it was always in MERCURY_OPTIONS which is used at runtime.
I think, but aren't certain, that defaults for MERCURY_OPTIONS can be set in
mkinit's parameters.

Good luck.


-- 
Paul Bone
http://www.bone.id.au



More information about the users mailing list