Hello all,
TLDR: The below MRE in C++ compiles (albeit with a warning) and runs fine when built with host clang on aarch64-darwin, but crashes with Trace/BPT trap: 5
when built with nix. What is happening differently that lets it build and run fine with host clang but crash when built with nix?
I don’t know C-family languages, would love some help wrapping my head around this issue.
After many moons I think I’ve finally sorted out espanso: runtime crash on aarch64-darwin · Issue #247162 · NixOS/nixpkgs · GitHub, which boils down to a void *
function that didn’t have an return value.
Part of what took me so long to sort this out is because clang emits a warning but seems to work fine when code violating this is compiled outside of nix (on darwin at least).
For example, an MRE:
// foo.h
#ifndef FOO_H
#define FOO_H
void *a_function(void);
#endif
// foo.cpp
#include "foo.h"
#include <iostream>
void *a_function() {
std::cerr << "hello from a function" << std::endl;
}
int main() {
a_function();
return 0;
}
Seems to work fine in darwin:
$ clang++ foo.cpp -o foo
foo.cpp:7:1: warning: non-void function does not return a value [-Wreturn-type]
}
^
1 warning generated.
$ echo $?
0
$ ./foo
hello from a function
$ echo $?
0
But if I build in nix, it won’t run:
$ cat default.nix
{clangStdenv}:
clangStdenv.mkDerivation {
name = "foo";
version = "0.0.1";
src = ./.;
buildPhase = ''
clang++ -o foo ./foo.cpp
'';
installPhase = ''
mkdir -p $out/bin
cp foo $out/bin/
'';
}
$
$ nix-build --expr '(import <nixpkgs> {}).callPackage ./. {}'
this derivation will be built:
/nix/store/m96r3b2fg7m8ajrj8lqv9gxgyrnwlhdg-foo.drv
building '/nix/store/m96r3b2fg7m8ajrj8lqv9gxgyrnwlhdg-foo.drv'...
Running phase: unpackPhase
unpacking source archive /nix/store/ix7hg847sf9ksihji6lb7lsaxvf5qksk-tmp.JsKJ1AKJ9z
source root is tmp.JsKJ1AKJ9z
Running phase: patchPhase
Running phase: updateAutotoolsGnuConfigScriptsPhase
Running phase: configurePhase
no configure script, doing nothing
Running phase: buildPhase
./foo.cpp:7:1: warning: non-void function does not return a value [-Wreturn-type]
}
^
1 warning generated.
Running phase: installPhase
Running phase: fixupPhase
checking for references to /private/tmp/nix-build-foo.drv-0/ in /nix/store/bs2xcdwsyxd1ljd59j0y6vf4w1770vpf-foo...
patching script interpreter paths in /nix/store/bs2xcdwsyxd1ljd59j0y6vf4w1770vpf-foo
stripping (with command strip and flags -S) in /nix/store/bs2xcdwsyxd1ljd59j0y6vf4w1770vpf-foo/bin
/nix/store/bs2xcdwsyxd1ljd59j0y6vf4w1770vpf-foo
$
$ ./result/bin/foo
hello from a function
Trace/BPT trap: 5
For context, the same code on an (arch) Linux machine errors at runtime:
$ clang++ foo.cpp -o foo
foo.cpp:7:1: warning: non-void function does not return a value [-Wreturn-type]
7 | }
| ^
1 warning generated.
$ ./foo
hello from a function
Illegal instruction (core dumped)
(NB: It runs fine under nix if I resolve the warning by adding return NULL;
to the end of a_function
.)