How can I investigate the cause of a segmentation fault?
I've encountered a segmentation fault when running tests for the phone-number exercise in attempting to debug my solution.
Tests code
app [main!] {
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br",
}
import pf.Stdout
main! = |_args|
Stdout.line!("")
import PhoneNumber exposing [clean]
# invalid when 11 digits does not start with a 1
expect
result = clean("22234567890")
result |> Result.is_err
# valid when 11 digits and starting with 1
expect
result = clean("12234567890")
expected = Ok("2234567890")
result == expected
PhoneNumber.roc
module [clean]
clean : Str -> Result Str _
clean = |phone_number|
parsed =
Str.to_utf8(phone_number)
|> List.keep_if(|c| c > '0' and c <= '9')
when parsed is
['1', a, _, _, b, .. as rest] if a > '1' and b > '1' and List.len(rest) == 6 -> Str.from_utf8(List.drop_first(parsed, 1))
[a, _, _, b, .. as rest] if a > '1' and b > '1' and List.len(rest) == 6 -> Str.from_utf8(parsed)
_ -> Err(InvalidFormat)
Interestingly if run the tests individually then no segmentation fault occurs. Also no segmentation fault if I alter the implementation (this corrects the logic so that all tests pass), by changing a GT to a GTE in the line:
List.keep_if(|c| c > '0' and c <= '9')
to
List.keep_if(|c| >= '0' and c <= '9')
I'm using:
roc nightly pre-release, built from commit c47a8e9cdac on Sat Mar 22 09:14:20 UTC 2025
Is the compiler segfaulting or the executable?
Oh, it's expects specifically
Probably the communication better compiler and test runner
Could try running with old or gdb
I was able to reproduce this and am checking it out with valgrind now
I switched the expects around and got some memory garbage in the output:
── EXPECT FAILED in temp.roc ───────────────────────────────────────────────────
This expectation failed:
12│> # valid when 11 digits and starting with 1
13│> expect
14│> result = clean("12234567890")
15│> expected = Ok("2234567890")
16│> result == expected
When it failed, these variables had these values:
result : Result Str [
BadUtf8 {
index : U64,
problem : Utf8Problem,
},
InvalidFormat,
]
result = Ok
"""
����Г
Eʪʪʪʲ234567890
"""
expected : [
Err [
BadUtf8 {
index : U64,
problem : Utf8Problem,
},
InvalidFormat,
],
Ok Str,
]
expected = Ok "2234567890"
This is likely very similar to
Hmm, the important valgrind error (at the end) is different from the one in the other thread.
valgrind_output_expect_phone_number_exercism.txt
This assertion is hit when building in debug mode: https://github.com/roc-lang/roc/blob/fac7041d11a70751f271c90dbf8354e746c18837/crates/repl_expect/src/app.rs#L25
Anyway, this does come down to
. If the new compiler takes too long we will fix this in the old compiler.@Tom Hill with the next release you will get a nicer error message, see PR#7773.
As a workaround you can write your own expect function:
my_expect! : Str, Result Str _ => Result {} _
my_expect! = |input, expected|
result = clean(input)
if result == expected then
Stdout.line!("Test passed for input: ${input}")
else
Stdout.line!("Test failed for input: ${input}. Expected: ${Inspect.to_str(expected)}, but got: ${Inspect.to_str(result)}")
Thank you for investigating :grinning:
I've made a general issue for this problem #7799
Last updated: Jul 05 2025 at 12:14 UTC