[m-users.] seg fault, 64 bit

Tomas By tomas at basun.net
Sat Jun 8 09:31:15 AEST 2013


Thanks for the reply. I am using the default grade (asm_fast?)

What confuses me is that it is not that much data, and 3GB is a ridiculous
amount of stack. I have run (what I believe to be) bigger computations on
32 bit machines with less than a GB total memory (this machine has 8GB).

I do not have any tail(or mistakenly non-tail)-recursive functions in my
code, only foldl's and traversal of recursive data structures.

The code that causes the problem is this:

| :- type tnfstats--->
| :- type vstats ---> vs(int,int,int,map(string,int),int,int).
| :- func new_vs = vstats.
| new_vs = vs(0,0,0,map.init,0,0).
| :- pred tnfiles_stats(list(tnfile)::in,tnfstats::out) is det.
| tnfiles_stats(Fs,Stats) :-
|   Stats0 = tnfs(new_vs,new_vs,new_vs,new_vs,map.init,map.init),
|   foldl(tnfile_stats,Fs,Stats0,Stats1),
|   Stats1 = tnfs(SS,PS,OS,RS,Cmap,Rmap),
|   map.foldl((pred(_::in,V::in,M0::in,M::out) is det :-
|     ( map.search(M0,V,N) ->
|       map.det_update(V,N+1,M0,M)
|     ; map.det_insert(V,1,M0,M) )),Cmap,map.init,Imap),
|   Stats = tnfs(SS,PS,OS,RS,Imap,Rmap).
| :- pred tnfile_stats(tnfile::in,tnfstats::in,tnfstats::out) is det.
| tnfile_stats(file(_,Chunks),!Stats) :-
|   foldl(chunk_stats,Chunks,!Stats).
| :- pred chunk_stats(chunk::in,tnfstats::in,tnfstats::out) is det.
| chunk_stats(chunk(_,_,_,_,_,Triples),!Stats) :-
|   foldl(triple_stats,Triples,!Stats).

where triple_stats/3 updates the tnfstats (no recursive calls).

Should I use some other data structure than map's?

The tnfile's vary a bit in size (by a factor ten or so), and there are
around a thousand of them.

Shouldn't the stack be back to `zero' at each iteration of
`foldl(tnfile_stats,Fs,Stats0,Stats1)' ?

If not, how does your suggestion to split the loops help?

(Will try your other suggestions)


On Sat, June 8, 2013 00:57, Paul Bone wrote:
> 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