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

PPL语言编译-1触发SEGV错误:LLVM IR或运行时库问题排查

问题描述

我正在开发一款名为PPL的编程语言,默认支持任意宽度的整数字面量,通过指向GMP库mpz_class的指针实现。但编译表达式-1时,地址 sanitizer报告SEGV错误:

==92833==ERROR: AddressSanitizer: SEGV on unknown address 0x000100000006 (pc 0x000105564bc4 bp 0x000105019f14 sp 0x00016ce45e50 T0)
==92833==The signal is caused by a UNKNOWN memory access.
    #0 0x105564bc4 in __gmpz_neg+0x14 (libgmp.10.dylib:arm64+0x14bc4) (BuildId: efc29ca33b2a3664976db890d76d3d0832000000200000000100000000000c00)

相关运行时代码

// Temporary solution for not leaking memory,
// as I haven't implemented memory management yet
std::unordered_set<mpz_class> values;

// PPL's big integer type
using Integer = const mpz_class *;

extern "C" {

// Used to create integer from literal
Integer _IntegerConstructorFromCString(const char *string)
{
    assert(string);
    // Inserts value and returns pointer to it
    return &*values.emplace(mpz_class(string)).first;
}

/// - <:Integer> -> Integer
Integer _MinusInteger(Integer value)
{
    // I checked in debugger, here value is 0x000100000006,
    // which isn't a pointer I returned from _IntegerConstructorFromCString

    assert(value); 
    // Inserts value and returns pointer to it
    return &*values.emplace(-*value).first;
}

} // extern "C"

编译器生成的LLVM IR

@.str = private unnamed_addr constant [2 x i8] c"1\00", align 1

// Code for "-1" top level expression
define void @_top_level_code() {
  // Create integer from "1"
  %1 = call ptr @_IntegerConstructorFromCString(ptr getelementptr inbounds ([2 x i8], ptr @.str, i32 0, i32 0))
  // Get -1
  %2 = call ptr @"- <:Integer>"(ptr %1)
  ret void
}

// Function from runtime
declare ptr @_MinusInteger(ptr %0)

// PPL's operator that hides runtime function invokation
define ptr @"- <:Integer>"(ptr %a) {
  %1 = load ptr, ptr %a, align 8
  %2 = call ptr @_MinusInteger(ptr %1)
  ret ptr %2
}

疑问:我的代码哪里存在问题?是否出在未使用alloca访问函数参数,或是某处未正确解引用指针?(因均为不透明类型,难以判断)

问题分析与解决

问题根源在LLVM IR的运算符实现函数"- <:Integer>"中,它执行了多余的指针加载操作,混淆了指针本身和指向指针的指针:

  1. 调用链路中的错误逻辑:

    • _top_level_code里,%1是_IntegerConstructorFromCString返回的Integer(即const mpz_class*),本身就是指向GMP整数对象的有效指针
    • 该指针被传给"- <:Integer>"的参数%a,但函数里却做了load ptr, ptr %a操作——这相当于把%a当成指针的指针来读取,取出的内容是无效的垃圾地址(也就是调试中看到的0x000100000006)
    • 把这个垃圾地址传给_MinusInteger后,解引用*value必然触发段错误
  2. 修复方案:
    删除多余的load操作,直接将参数%a传给_MinusInteger。修改后的LLVM IR运算符函数如下:

    define ptr @"- <:Integer>"(ptr %a) {
      %1 = call ptr @_MinusInteger(ptr %a)
      ret ptr %1
    }
    
  3. 额外说明:
    运行时代码本身没有问题,Integer类型定义为const mpz_class*合理,_IntegerConstructorFromCString和_MinusInteger的实现逻辑正确,错误完全来自LLVM IR层面的指针处理失误。


内容的提问来源于stack exchange,提问作者gavrilikhin.d

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:11:39