You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C程序因printf触发段错误且无编译警告,aarch64 Android环境复现

问题描述

以下是一段运行时触发段错误的简短C程序,即便在clang的pedantic严格编译级别下也无任何警告:

#include <stdio.h>
#include <stdlib.h>

typedef struct object {
    int type;
} object;

void write(object *obj) {
    switch (obj->type) {
    case 1:
        break;
    }
}

int main(void) {
    printf("hi");
    return 0;
}

该段错误仅在aarch64 Android环境中触发,x86 Linux环境下无此问题,相关环境信息如下:

$ gcc --version
clang version 17.0.6
Target: aarch64-unknown-linux-android24
Thread model: posix
InstalledDir: /data/data/com.termux/files/usr/bin

$ uname -a
Linux localhost 5.10.177-android13-4-00003-ga7208022a7ea-ab10815828 #1 SMP PREEMPT Fri Sep 15 16:40:54 UTC 2023 aarch64 Android

通过gdb调试发现,printf最终会调用自定义的write函数,移除main中的printf或自定义write函数后,程序可正常运行。

原因分析

核心问题是全局符号冲突:

  • 标准C库(libc)中存在系统调用write,用于向文件描述符写入数据,printf最终会调用这个系统级write输出内容。
  • 自定义的write函数未加static修饰,属于全局符号。在aarch64 Android的链接器规则下,该全局符号会覆盖libc中的同名符号,导致printf调用时实际执行的是自定义write函数。
  • 系统级write的参数为(int fd, const void *buf, size_t count),而自定义write的参数是(object *obj),参数类型完全不匹配。当printf传递系统级参数给自定义函数时,函数会错误地将这些参数解析为object*类型,访问obj->type时触发非法内存访问,进而导致段错误。

x86 Linux环境未出现问题,大概率是因为该平台下libc的write符号被标记为强符号,或者链接器的符号解析优先级不同,自定义全局符号无法覆盖系统库中的同名符号,因此printf仍调用正确的系统write。

解决方案

有两种简单的修复方式:

  1. 给自定义write函数添加static修饰,将其限制为文件内局部符号,避免与全局系统write冲突:
static void write(object *obj) {
    switch (obj->type) {
    case 1:
        break;
    }
}
  1. 直接给自定义函数改名(比如object_write),从根源上避免同名冲突。

内容的提问来源于stack exchange,提问作者Tumok A. Byrd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 09:52:40