为什么交叉编译的程序会这样崩溃?

问题描述 投票:0回答:1

我为 Raspberry Pi Zero 交叉编译了程序,但由于某种原因我崩溃了。程序很简单,只是打印字符串到

std::cout
:

#include <iostream>

int main(int argc, char const *argv[])
{
    std::cout << "Hello!" << std::endl;
    return 0;
}

我使用 Docker 和 CMake 构建程序:

FROM debian:bookworm

ENV GNU_HOST=arm-linux-gnueabihf
ENV C_COMPILER_ARM_LINUX=$GNU_HOST-gcc
ENV CXX_COMPILER_ARM_LINUX=$GNU_HOST-g++

ENV CROSS_INSTALL_PREFIX=/usr/$GNU_HOST
ENV CROSS_TOOLCHAIN=/arm.toolchain.cmake

RUN echo "set(CMAKE_SYSTEM_NAME Linux)" >> $CROSS_TOOLCHAIN && \
  echo "set(CMAKE_SYSTEM_PROCESSOR arm)" >> $CROSS_TOOLCHAIN && \
  echo "set(CMAKE_C_COMPILER /usr/bin/$C_COMPILER_ARM_LINUX)" >> $CROSS_TOOLCHAIN && \
  echo "set(CMAKE_CXX_COMPILER /usr/bin/$CXX_COMPILER_ARM_LINUX)" >> $CROSS_TOOLCHAIN && \
  echo "set(CMAKE_PREFIX_PATH $CROSS_INSTALL_PREFIX)" >> $CROSS_TOOLCHAIN

RUN apt-get update && \
  apt-get --no-install-recommends install -y autoconf \
    automake \
    build-essential \
    ca-certificates \
    curl \
    # C/C++ cross compilers
    gcc-$GNU_HOST \
    g++-$GNU_HOST \
    git \
    gnupg \
    libssl-dev \
    openssh-client \
    pkg-config \
    software-properties-common \
    wget \
    cmake && \
  rm -rf /var/lib/apt/lists/*

这是 C++ 编译器版本:

/usr/bin/arm-linux-gnueabihf-g++ --version
arm-linux-gnueabihf-g++ (Debian 12.2.0-14) 12.2.0

这里是有关二进制文件的信息。

pi@raspberrypi:~$ file camera-bot
camera-bot: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=f45663f061217dc844ca45f314e2af084df83869, for GNU/Linux 3.2.0, with debug_info, not stripped
pi@raspberrypi:~$ objdump -j .interp -s ./camera-bot

./camera-bot:     file format elf32-littlearm

Contents of section .interp:
 0154 2f6c6962 2f6c642d 6c696e75 782d6172  /lib/ld-linux-ar
 0164 6d68662e 736f2e33 00                 mhf.so.3.       
pi@raspberrypi:~$ 
pi@raspberrypi:~$ ldd camera-bot
        /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => /usr/lib/arm-linux-gnueabihf/libarmmem-v6l.so (0xb6ee0000)
        libstdc++.so.6 => /lib/arm-linux-gnueabihf/libstdc++.so.6 (0xb6d00000)
        libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0xb6cc0000)
        libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6b47000)
        libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0xb6b00000)
        /lib/ld-linux-armhf.so.3 (0xb6f23000)
pi@raspberrypi:~$ g++ --version
g++ (Raspbian 12.2.0-14+rpi1) 12.2.0
Copyright (C) 2022 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:~$ gdb camera-bot
GNU gdb (Raspbian 13.1-3) 13.1

Reading symbols from camera-bot...
(gdb) b main
Breakpoint 1 at 0x892: file /workspaces/RaspberryCamera/src/main.cpp, line 19.
(gdb) run
Starting program: /home/pi/camera-bot 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x0044f952 in ?? ()
(gdb) bt
#0  0x0044f952 in ?? ()
#1  0x0040079e in _start ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

更新#1

即使我对 C++ 标准库进行静态链接,也会崩溃:

Reading symbols from camera-bot...
(gdb) b main
Breakpoint 1 at 0x889a: file /workspaces/RaspberryCamera/src/main.cpp, line 19.
(gdb) run
Starting program: /home/pi/camera-bot 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x0045795c in bool std::has_facet<std::collate<wchar_t> >(std::locale const&) ()
(gdb) bt
#0  0x0045795c in bool std::has_facet<std::collate<wchar_t> >(std::locale const&) ()
#1  0xbefff6e2 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
c++ linux raspberry-pi-zero
1个回答
0
投票

我发现用于交叉编译的 Docker 镜像

debian:bookworm
具有专为 ARMv8 构建的
/usr/bin/arm-linux-gnueabihf
编译器,但 Raspberry Pi Zero 需要 ARMv6。还有一些其他 ARM 相关选项,对于设备编译器和 Docker 映像编译器来说是不同的。我猜这就是崩溃的原因。

因此,我将 Docker 映像更改为由

tttapa
创建的 ghcr.io/tttapa/docker-arm-cross-toolchain:armv6-rpi-linux-gnueabihf,并在我的 CMakeLists.txt 中启用了 C++ 标准库的静态链接。

# Dockerfile.dev
FROM ghcr.io/tttapa/docker-arm-cross-toolchain:armv6-rpi-linux-gnueabihf

USER root

RUN apt-get update && \
  apt-get --no-install-recommends install -y autoconf \
    automake \
    build-essential \
    ca-certificates \
    curl \
    gnupg \
    libssl-dev \
    openssh-client \
    pkg-config \
    software-properties-common \
    wget \
    cmake && \
  rm -rf /var/lib/apt/lists/*

完成此步骤后,我可以在 Raspberry Pi Zero 上运行交叉编译的二进制文件,而不会发生任何崩溃。

附注我不知道这是否应该被接受,因为我没有在我的问题中提供来自 Docker 映像和设备的 GCC 的完整版本信息(包括构建选项)。也许这个答案将为面临同样崩溃的人节省一些时间。

© www.soinside.com 2019 - 2024. All rights reserved.