Fmt: argument not found on ARM linux only

Created on 6 Oct 2020  路  21Comments  路  Source: fmtlib/fmt

The following code

#include <fmt/core.h>
#include <iostream>

int main() {
    std::cout << fmt::format("{0}, {1}, {2}", 'a', 'b', 'c');
    return 0;
}

compiled with

clang++ fmttest.cpp -o fmttest /usr/local/lib/libfmt.a

on archlinuxarm gives

./fmttest
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found

while on MacOS it gives

./fmttest
a, b, c

Both versions are compiled from source from the latest source version.

However, compiling with format.cc seems to solve the issue:

clang++ fmttest.cpp -o fmttest -I /home/user/Downloads/fmt/include /home/user/Downloads/fmt/build/libfmt.a -v
./fmttest
./fmttest
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Aborted (core dumped)
clang++ fmttest.cpp -o fmttest -I /home/user/Downloads/fmt/include /home/user/Downloads/fmt/src/format.cc -v
./fmttest
a, b, c

All 21 comments

I don't have an ARM box to repro so you'll need to provide more details, e.g. the exception stack trace and exact version (or commit hash).

Also I recommend a clean rebuild from source to make sure you don't have an incompatible version of the library (which is the most likely cause).

git log
commit 7277035736eb991207d8f95077e607b68f4b5ebe (HEAD -> master, origin/master, origin/HEAD)
Author: francesco-st <[email protected]>
Date:   Mon Oct 5 15:42:02 2020 +0200

    Fix long lines in usage.md
clang++ fmttest.cpp -o fmttest -I /home/user/Downloads/fmt/include /home/user/Downloads/fmt/build/libfmt.a -v -g
lldb ./fmttest
r
bt
Process 24229 launched: '/tmp/fmttest' (arm)
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Process 24229 stopped
* thread #1, name = 'fmttest', stop reason = signal SIGABRT
    frame #0: 0x76c71aa0 libc.so.6`raise + 188
libc.so.6`raise:
->  0x76c71aa0 <+188>: ldr    r2, [pc, #0x50]           ; <+276>
    0x76c71aa4 <+192>: ldr    r3, [pc, #0x48]           ; <+272>
    0x76c71aa8 <+196>: add    r2, pc, r2
    0x76c71aac <+200>: ldr    r3, [r2, r3]
(lldb) bt
* thread #1, name = 'fmttest', stop reason = signal SIGABRT
  * frame #0: 0x76c71aa0 libc.so.6`raise + 188
    frame #1: 0x76c5ad7c libc.so.6`abort + 276
    frame #2: 0x76eb0848 libstdc++.so.6`__gnu_cxx::__verbose_terminate_handler() at vterminate.cc:95:10
    frame #3: 0x76eae0ac libstdc++.so.6`__cxxabiv1::__terminate(handler=<unavailable>)()) at eh_terminate.cc:48:15
    frame #4: 0x76eae138 libstdc++.so.6`std::terminate() at eh_terminate.cc:58:15
    frame #5: 0x76eae508 libstdc++.so.6`__cxxabiv1::__cxa_throw(obj=<unavailable>, tinfo=<unavailable>, dest=<unavailable>)(void *)) at eh_throw.cc:95:18
    frame #6: 0x00401670 fmttest`fmt::v7::detail::error_handler::on_error(char const*) (.constprop.0) + 72
    frame #7: 0x00415530 fmttest`char const* fmt::v7::detail::parse_replacement_field<char, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&>(char const*, char const*, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&) + 340
    frame #8: 0x004161cc fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::iterator fmt::v7::vformat_to<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >(fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>::iterator, fmt::v7::basic_string_view<char>, fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >, fmt::v7::detail::locale_ref) + 1692
    frame #9: 0x0041650c fmttest`fmt::v7::detail::buffer_appender<char> fmt::v7::detail::vformat_to<char>(fmt::v7::detail::buffer<char>&, fmt::v7::basic_string_view<char>, fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<fmt::v7::type_identity<char>::type>, fmt::v7::type_identity<char>::type> >) + 52
    frame #10: 0x00402e64 fmttest`fmt::v7::detail::vformat[abi:cxx11](fmt::v7::basic_string_view<char>, fmt::v7::format_args) + 144
    frame #11: 0x00401da4 fmttest`main [inlined] std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > fmt::v7::format<char [14], char, char, char, char>(format_str=<no value available>, args=0x7efffaa7, args=0x7efffaa6, args=0x7efffaa5) [14], char&&, char&&, char&&) at core.h:2083:10
    frame #12: 0x00401ce0 fmttest`main at fmttest.cpp:5
    frame #13: 0x76c5b154 libc.so.6`__libc_start_main + 272
    frame #14: 0x00401b40 fmttest`_start + 68

I can confirm it is a clean rebuild as there are no fmt files anywhere on the system

find / -name fmt
/usr/bin/fmt
find / -name core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/sound/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/cec/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/iio/st/sensors/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/async/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mma9551/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/elf/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mfd/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mfd/rpisense/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/sound/oss/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/touchscreen/cyttsp/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/touchscreen/tsc200x/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/touchscreen/cyttsp4/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/videobuf2/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/wext/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/watchdog/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/serial/sc16is7xx/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/serial/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/rmi4/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mtd/nand/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mt76/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/tcg/tis/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/net/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/usbip/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/dvb/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/rc/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/arch/has/membarrier/sync/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/target/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mmc/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/mt6397/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/wm8350/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/madera/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9062/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/mt6323/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/arizona/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/samsung/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/wm831x/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9150/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/pcf50633/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/wm8994/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/rpisense/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9063/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9055/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/can/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/net/netns/core.h



md5-db8522919bccf48f80a77166e86815b6



clang++ ./fmttest.cpp  -o fmttest-l fmt
./fmttest.cpp:1:10: fatal error: 'fmt/core.h' file not found
#include <fmt/core.h>
         ^~~~~~~~~~~~
1 error generated.



md5-db8522919bccf48f80a77166e86815b6



git clone https://github.com/fmtlib/fmt.git
cd fmt && mkdir build && cd build && cmake .. && make 
sudo make install



md5-db8522919bccf48f80a77166e86815b6



clang++ ./fmttest.cpp  -o fmttest -l fmt
./fmttest

terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Aborted (core dumped)



md5-db8522919bccf48f80a77166e86815b6



find / -name fmt
/usr/bin/fmt
/usr/local/lib/cmake/fmt
/usr/local/include/fmt
/tmp/fmt
/tmp/fmt/build/CMakeFiles/Export/lib/cmake/fmt
/tmp/fmt/include/fmt



md5-db8522919bccf48f80a77166e86815b6



 find / -name core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/sound/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/cec/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/iio/st/sensors/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/async/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mma9551/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/elf/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mfd/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mfd/rpisense/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/sound/oss/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/touchscreen/cyttsp/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/touchscreen/tsc200x/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/touchscreen/cyttsp4/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/videobuf2/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/wext/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/watchdog/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/serial/sc16is7xx/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/serial/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/rmi4/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mtd/nand/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/mt76/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/tcg/tis/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/net/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/usbip/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/dvb/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/rc/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/arch/has/membarrier/sync/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/config/target/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mmc/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/mt6397/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/wm8350/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/madera/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9062/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/mt6323/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/arizona/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/samsung/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/wm831x/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9150/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/pcf50633/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/wm8994/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/rpisense/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9063/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/mfd/da9055/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/linux/can/core.h
/usr/lib/modules/5.4.65-1-ARCH/build/include/net/netns/core.h
/usr/local/include/fmt/core.h
/tmp/fmt/include/fmt/core.h

Could you build libfmt with debug information and post the stack trace for that? Otherwise there are no locations.

 clang++ ./fmttest.cpp -o fmttest -l fmtd -g
 lldb ./fmttest
(lldb) target create "./fmttest"
Current executable set to '/tmp/fmttest' (arm).
(lldb) r
Process 27873 launched: '/tmp/fmttest' (arm)
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Process 27873 stopped
* thread #1, name = 'fmttest', stop reason = signal SIGABRT
    frame #0: 0x76c71aa0 libc.so.6`raise + 188
libc.so.6`raise:
->  0x76c71aa0 <+188>: ldr    r2, [pc, #0x50]           ; <+276>
    0x76c71aa4 <+192>: ldr    r3, [pc, #0x48]           ; <+272>
    0x76c71aa8 <+196>: add    r2, pc, r2
    0x76c71aac <+200>: ldr    r3, [r2, r3]
(lldb) bt
* thread #1, name = 'fmttest', stop reason = signal SIGABRT
  * frame #0: 0x76c71aa0 libc.so.6`raise + 188
    frame #1: 0x76c5ad7c libc.so.6`abort + 276
    frame #2: 0x76eb0848 libstdc++.so.6`__gnu_cxx::__verbose_terminate_handler() at vterminate.cc:95:10
    frame #3: 0x76eae0ac libstdc++.so.6`__cxxabiv1::__terminate(handler=<unavailable>)()) at eh_terminate.cc:48:15
    frame #4: 0x76eae138 libstdc++.so.6`std::terminate() at eh_terminate.cc:58:15
    frame #5: 0x76eae508 libstdc++.so.6`__cxxabiv1::__cxa_throw(obj=<unavailable>, tinfo=<unavailable>, dest=<unavailable>)(void *)) at eh_throw.cc:95:18
    frame #6: 0x004036dc fmttest`fmt::v7::detail::error_handler::on_error(this=0x7efff610, message="argument not found") at format-inl.h:2736:3
    frame #7: 0x0041bbf4 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::on_error(this=0x7efff738, message="argument not found") at core.h:1539:64
    frame #8: 0x00419f48 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::format_arg fmt::v7::detail::get_arg<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>, int>(ctx=0x7efff738, id=0) at format.h:2432:25
    frame #9: 0x00415ca4 fmttest`char const* fmt::v7::detail::parse_replacement_field<char, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&>(char const*, char const*, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&) [inlined] fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >::on_replacement_field((null)="}, {1}, {2}", id=0, this=0x7efff728) at format.h:2930:23
    frame #10: 0x00415c8c fmttest`char const* fmt::v7::detail::parse_replacement_field<char, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&>(begin="}, {1}, {2}", end="", handler=0x7efff728) at format.h:2826
    frame #11: 0x0040e044 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::iterator fmt::v7::vformat_to<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >(fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>::iterator, fmt::v7::basic_string_view<char>, fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >, fmt::v7::detail::locale_ref) at format.h:2850:44
    frame #12: 0x0040df9c fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::iterator fmt::v7::vformat_to<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >(out=fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>::iterator @ 0x7efff6f4, format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> > @ 0x7efff770, loc=(locale_ = 0x00000000)) at format.h:3496
    frame #13: 0x004092c4 fmttest`fmt::v7::detail::buffer_appender<char> fmt::v7::detail::vformat_to<char>(buf=0x7efff844, format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> > @ 0x7efff7b0) at format.h:3671:24
    frame #14: 0x00403ae8 fmttest`fmt::v7::detail::vformat[abi:cxx11](format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=format_args @ 0x7efffa60) at format-inl.h:2751:46
    frame #15: 0x00402774 fmttest`main [inlined] std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > fmt::v7::format<char [14], char, char, char, char>(format_str=<no value available>, args=0x7efffab7, args=0x7efffab6, args=0x7efffab5) [14], char&&, char&&, char&&) at core.h:2083:10
    frame #16: 0x004026b0 fmttest`main at fmttest.cpp:5
    frame #17: 0x76c5b154 libc.so.6`__libc_start_main + 272
    frame #18: 0x00402510 fmttest`_start + 68

The stack trace shows that ctx.arg(0) returns an empty argument in

https://github.com/fmtlib/fmt/blob/7277035736eb991207d8f95077e607b68f4b5ebe/include/fmt/format.h#L2431

although it's unclear why this happens since the ctx should contain 3 char arguments.

lldb confirms this:
```
(lldb) r
There is a running process, kill it and restart?: [Y/n] y
Process 27873 exited with status = 9 (0x00000009)
Process 27961 launched: '/tmp/fmttest' (arm)
Process 27961 stopped

  • thread #1, name = 'fmttest', stop reason = breakpoint 1.1
    frame #0: 0x00419f04 fmttest`fmt::v7::basic_format_context, char>::format_arg fmt::v7::detail::get_arg, char>, int>(ctx=0x7efff738, id=0) at format.h:2431:21
    2428
    2429 template
    2430 FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, ID id) {
    -> 2431 auto arg = ctx.arg(id);
    2432 if (!arg) ctx.on_error("argument not found");
    2433 return arg;
    2434 }
    (lldb) e ctx
    (fmt::v7::basic_format_context, char>) $0 = {
    out_ = {
    std::back_insert_iterator > = {
    container = 0x7efff844
    }
    }
    args_ = {
    desc_ = 9151308842179493888
    = {
    values_ = 0x7efffaec
    args_ = 0x7efffaec
    }
    }
    loc_ = (locale_ = 0x00000000)
    }
    (lldb) e id
    (int) $1 = 0
    (lldb) e ctx.arg(id)
    (fmt::v7::basic_format_context, char>::format_arg) $2 = {
    value_ = {
    = {
    int_value = 0
    uint_value = 0
    long_long_value = 0
    ulong_long_value = 0
    int128_value = {}
    uint128_value = {}
    bool_value = false
    char_value = '0'
    float_value = 0
    double_value = 0
    long_double_value = 0
    pointer = 0x00000000
    string = (data = , size = 0)
    custom = {
    value = 0x00000000
    format = 0x00000000
    }
    named_args = {
    data = 0x00000000
    size = 0
    }
    }
    }
    type_ = none_type
    }
    ````

This question is probably just noise, but does this happen with ints, too? Or just chars?

With numbers the result is the same and stack trace shows the same path.

cat ./fmttest.cpp
#include <fmt/core.h>
#include <iostream>

int main() {
    std::cout << fmt::format("{0}, {1}, {2}", 1, 2, 42);
    return 0;
}
clang++ ./fmttest.cpp -o fmttest -l fmtd -g
lldb ./fmttest
(lldb) r
Process 28025 launched: '/tmp/fmttest' (arm)
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Process 28025 stopped
* thread #1, name = 'fmttest', stop reason = signal SIGABRT
    frame #0: 0x76c71aa0 libc.so.6`raise + 188
libc.so.6`raise:
->  0x76c71aa0 <+188>: ldr    r2, [pc, #0x50]           ; <+276>
    0x76c71aa4 <+192>: ldr    r3, [pc, #0x48]           ; <+272>
    0x76c71aa8 <+196>: add    r2, pc, r2
    0x76c71aac <+200>: ldr    r3, [r2, r3]
(lldb) bt
* thread #1, name = 'fmttest', stop reason = signal SIGABRT
  * frame #0: 0x76c71aa0 libc.so.6`raise + 188
    frame #1: 0x76c5ad7c libc.so.6`abort + 276
    frame #2: 0x76eb0848 libstdc++.so.6`__gnu_cxx::__verbose_terminate_handler() at vterminate.cc:95:10
    frame #3: 0x76eae0ac libstdc++.so.6`__cxxabiv1::__terminate(handler=<unavailable>)()) at eh_terminate.cc:48:15
    frame #4: 0x76eae138 libstdc++.so.6`std::terminate() at eh_terminate.cc:58:15
    frame #5: 0x76eae508 libstdc++.so.6`__cxxabiv1::__cxa_throw(obj=<unavailable>, tinfo=<unavailable>, dest=<unavailable>)(void *)) at eh_throw.cc:95:18
    frame #6: 0x004036dc fmttest`fmt::v7::detail::error_handler::on_error(this=0x7efff608, message="argument not found") at format-inl.h:2736:3
    frame #7: 0x0041baf4 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::on_error(this=0x7efff730, message="argument not found") at core.h:1539:64
    frame #8: 0x00419e48 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::format_arg fmt::v7::detail::get_arg<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>, int>(ctx=0x7efff730, id=0) at format.h:2432:25
    frame #9: 0x00415bf0 fmttest`char const* fmt::v7::detail::parse_replacement_field<char, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&>(char const*, char const*, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&) [inlined] fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >::on_replacement_field((null)="}, {1}, {2}", id=0, this=0x7efff720) at format.h:2930:23
    frame #10: 0x00415bd8 fmttest`char const* fmt::v7::detail::parse_replacement_field<char, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&>(begin="}, {1}, {2}", end="", handler=0x7efff720) at format.h:2826
    frame #11: 0x0040e044 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::iterator fmt::v7::vformat_to<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >(fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>::iterator, fmt::v7::basic_string_view<char>, fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >, fmt::v7::detail::locale_ref) at format.h:2850:44
    frame #12: 0x0040df9c fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::iterator fmt::v7::vformat_to<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >(out=fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>::iterator @ 0x7efff6ec, format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> > @ 0x7efff768, loc=(locale_ = 0x00000000)) at format.h:3496
    frame #13: 0x004092c4 fmttest`fmt::v7::detail::buffer_appender<char> fmt::v7::detail::vformat_to<char>(buf=0x7efff83c, format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> > @ 0x7efff7a8) at format.h:3671:24
    frame #14: 0x00403ae8 fmttest`fmt::v7::detail::vformat[abi:cxx11](format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=format_args @ 0x7efffa58) at format-inl.h:2751:46
    frame #15: 0x00402774 fmttest`main [inlined] std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > fmt::v7::format<char [14], int, int, int, char>(format_str=<no value available>, args=0x7efffab4, args=0x7efffab0, args=0x7efffaac) [14], int&&, int&&, int&&) at core.h:2083:10
    frame #16: 0x004026b0 fmttest`main at fmttest.cpp:5
    frame #17: 0x76c5b154 libc.so.6`__libc_start_main + 272
    frame #18: 0x00402510 fmttest`_start + 68

This seems to be LLVM specific. The library has been compiled with GCC

cat ./fmttest.cpp
#include <fmt/core.h>
#include <iostream>

int main() {
    std::cout << fmt::format("{0}, {1}, {2}", 1, 2, 42);
    return 0;
}
g++ ./fmttest.cpp -o fmttest -l fmtd -g
./fmttest
1, 2, 42
clang++ ./fmttest.cpp -o fmttest -l fmtd -g
./fmttest
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Aborted (core dumped)

compiling fmt with clang

CC=clang CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug

gives

clang++ fmttest.cpp -o fmttest -l fmtd -g
./fmttest
1, 2, 42
g++ fmttest.cpp -o fmttest -l fmtd -g
./fmttest
Segmentation fault (core dumped)
lldb ./fmttest
(lldb) target create "./fmttest"
Current executable set to '/tmp/fmttest' (arm).
(lldb) r
Process 28591 launched: '/tmp/fmttest' (arm)
Process 28591 stopped
* thread #1, name = 'fmttest', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
    frame #0: 0x00405020 fmttest`fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >::get(this=0x7efff5f0, id=0) const at core.h:1922:16
   1919     if (id >= detail::max_packed_args) return arg;
   1920     arg.type_ = type(id);
   1921     if (arg.type_ == detail::type::none_type) return arg;
-> 1922     arg.value_ = values_[id];
   1923     return arg;
   1924   }
   1925
(lldb) bt
* thread #1, name = 'fmttest', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
  * frame #0: 0x00405020 fmttest`fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >::get(this=0x7efff5f0, id=0) const at core.h:1922:16
    frame #1: 0x00417c18 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::arg(this=0x7efff5e8, id=0) const at core.h:1533:47
    frame #2: 0x00417b4c fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::format_arg fmt::v7::detail::get_arg<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>, int>(ctx=0x7efff5e8, id=0) at format.h:2431:18
    frame #3: 0x00416b18 fmttest`char const* fmt::v7::detail::parse_replacement_field<char, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&>(char const*, char const*, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&) [inlined] fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >::on_replacement_field(this=0x7efff5d8, id=0, (null)="}, {1}, {2}") at format.h:2930:16
    frame #4: 0x00416af4 fmttest`char const* fmt::v7::detail::parse_replacement_field<char, fmt::v7::detail::format_handler<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >&>(begin="}, {1}, {2}", end="", handler=0x7efff5d8) at format.h:2826
    frame #5: 0x00405b68 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::iterator fmt::v7::vformat_to<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >(fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>::iterator, fmt::v7::basic_string_view<char>, fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >, fmt::v7::detail::locale_ref) at format.h:2850:21
    frame #6: 0x00405ac0 fmttest`fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char>::iterator fmt::v7::vformat_to<fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>, char, fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> >(out=fmt::v7::detail::arg_formatter<fmt::v7::detail::buffer_appender<char>, char>::iterator @ 0x7efff59c, format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> > @ 0x7efff638, loc=(locale_ = 0x00000000)) at format.h:3496
    frame #7: 0x00405120 fmttest`fmt::v7::detail::buffer_appender<char> fmt::v7::detail::vformat_to<char>(buf=0x7efff864, format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<char>, char> > @ 0x7efff6b8) at format.h:3671:10
    frame #8: 0x004041f0 fmttest`fmt::v7::detail::vformat[abi:cxx11](format_str=(data_ = "{0}, {1}, {2}", size_ = 13), args=format_args @ 0x7efff850) at format-inl.h:2751:3
    frame #9: 0x00402a5c fmttest`main [inlined] std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > fmt::v7::format<char [14], int, int, int, char>((null)=<unavailable>, (null)=<unavailable>, (null)=<unavailable>, format_str=<unavailable>) [14], int&&, int&&, int&&) at core.h:2083:59
    frame #10: 0x004029c0 fmttest`main at fmttest.cpp:5
    frame #11: 0x76c5b154 libc.so.6`__libc_start_main + 272
    frame #12: 0x0040283c fmttest`_start + 68

The value of ctx.args_.desc_ is incorrect:

desc_ = 9151308842179493888

It should be 2184 (0x888) and the current value resembles a pointer (0x7efffae800000000). It looks like there is some incompatibility between clang and gcc.

on LLVM discord they said it is similar to https://github.com/itanium-cxx-abi/cxx-abi/issues/66

I just confirmed that also on other ARM build this problem occurs. With Fedora it is possible to run arm relatively easy:

https://fedoraproject.org/wiki/QA:Testcase_Virt_ARM_on_x86

resizing that image to create some space, install llvm, clang git and cmake on it and run it.

g++ fmttest.cpp -o fmttest -I ~/fmt/include -L ~/fmt/build -lfmt
clang++ fmttest.cpp -o fmttestclang -I ~/fmt/include -L ~/fmt/build -lfmt
./fmttest
a, b, c[root@localhost fmttest]#./fmttestclang
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Aborted (core dumped)

It's strange this problem does not occur on x86 Linux

Interestingly, it doesn't happen on all ARM systems (or could depend on compiler version). For example, on my Raspberry PI gcc and clang generate compatible code:

pi@raspberrypi:~/fmt $ g++ --version
g++ (Raspbian 4.9.2-10+deb8u2) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

pi@raspberrypi:~/fmt $ clang++ --version
Raspbian clang version 3.5.0-10+rpi1 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: arm-unknown-linux-gnueabihf
Thread model: posix
pi@raspberrypi:~/fmt $ cat test.cc
#include <fmt/core.h>
#include <iostream>

int main() {
    std::cout << fmt::format("{0}, {1}, {2}", 'a', 'b', 'c');
    return 0;
}
pi@raspberrypi:~/fmt $ clang++ test.cc -std=c++11 libfmt.a  -I include
pi@raspberrypi:~/fmt $ ./a.out
a, b, cpi@raspberrypi:~
pi@raspberrypi:~/fmt $ g++ test.cc -std=c++11 libfmt.a  -I include
pi@raspberrypi:~/fmt $ ./a.out
a, b, c

These are prehistorical versions of llvm and gcc, I used gcc 10 and llvm 11. I ran archlinux on rpi4 to have latest versions of these compilers

Managed to repro the issue on Raspberry Pi 4 with clang version 7.0.1-8+rpi3+deb10u2 (tags/RELEASE_701/final) and gcc (Raspbian 8.3.0-6+rpi1) 8.3.0 and implemented a workaround in https://github.com/fmtlib/fmt/commit/e50ced88c6f0db6c7c2e16cfb9aec4c9ab4df09c.

The workaround is enabled by defining the FMT_ARM_ABI_COMPATIBILITY macro:

git clone https://github.com/fmtlib/fmt.git
cd fmt
cmake -DCMAKE_CXX_FLAGS=-DFMT_ARM_ABI_COMPATIBILITY .
make fmt
cat >> test.cc << EOF
#include <fmt/core.h>
#include <iostream>

int main() {
    std::cout << fmt::format("{0}, {1}, {2}", 'a', 'b', 'c');
    return 0;
}
EOF
clang++ -DFMT_ARM_ABI_COMPATIBILITY test.cc -Iinclude -lfmt -L.
./a.out

Output:

a, b, c

The workaround will become the default in the next major release since it is ABI breaking.

Thanks for reporting.

Hi vitaut,

thanks for the work done. I'm on e50ced88c6f0db6c7c2e16cfb9aec4c9ab4df09c, which is

Date:   Sat Oct 31 07:51:39 2020 -0700

    Add a macro to workaround clang/gcc ABI incompatibility on ARM

and I compiled by using cmake .. with gcc 10.2.0, installed it and verified it overwrote /usr/local/lib/ilbfmt.a to the newest version.

$ cat ./test.cpp
#include <fmt/core.h>
#include <iostream>

int main() {
    std::cout << fmt::format("{0}, {1}, {2}", 'a', 'b', 'c');
    return 0;
}
$ clang++ --version
clang version 10.0.1
Target: armv7l-unknown-linux-gnueabihf
Thread model: posix
InstalledDir: /usr/bin
$ clang++ ./test.cpp -o test /usr/local/lib/libfmt.a
$ ./test
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Aborted (core dumped)

I think the LLVM and GCC versions are too old, they are from 2018 and beginning of 2019 respectively. Newer versions still fail.

The raspberry pi 4 is powerful enough to compile llvm from source to checkout head, but other than that with Debian I have no idea how to get newer versions on your system. Problems with old versions of software were my main reason never to use Debian again.

Ah, sorry I missed the CMake flag, will recompile it now again.

Not just CMake but compiler too. You are missing the flag in both places.

Yes, now it works, thanks for the fix! Next major release will be fmt 8, that will be next year right? I see a lot of activity, do you work on this project fulltime? Great work btw.

Thanks for verifying the fix.

Next major release will be fmt 8, that will be next year right?

Yes.

I see a lot of activity, do you work on this project fulltime?

No, only part time.

Was this page helpful?
0 / 5 - 0 ratings