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

使用std::format_args触发AddressSanitizer栈越界访问错误求助

std::format_args配合std::vformat触发stack-use-after-scope的原因解析

问题重现

代码示例:

#include <format>
#include <iostream>
#include <string>

int main() {
    int i = 42;
    std::string s = "hello";
    std::format_args args = std::make_format_args(i, s);
    std::cout << std::vformat("Number: {}, Word: {}", args) << '\n';

    return 0;
}

编译命令:
clang++-17 --std=c++23 -stdlib=libc++ -fsanitize=address fmt.cpp

运行后触发AddressSanitizer的stack-use-after-scope错误,但将std::make_format_args直接传入std::vformat则运行正常,且变量i和s仍在作用域内,无法理解错误原因。

错误原因

核心问题在于std::format_args是仅持有引用的轻量级视图类型,而std::make_format_args的实现中,会为传入的参数创建一系列临时包装对象(存储在栈上),std::format_args保存的是对这些临时对象的引用,而非直接引用原变量i和s。

当std::make_format_args调用结束后,其内部创建的临时包装对象会立即被销毁,此时args持有的引用就指向了已释放的栈内存。后续调用std::vformat时,通过这些引用访问已销毁的对象,就会触发stack-use-after-scope错误。

如果直接将std::make_format_args(i, s)传入std::vformat,根据C++临时对象生命周期规则,这些临时包装对象的生命周期会被延长至整个std::vformat函数调用期间,因此不会出现内存访问问题。

正确写法

直接传入参数(推荐)

如果不需要单独存储std::format_args,直接在std::vformat调用中传入std::make_format_args的结果即可:

#include <format>
#include <iostream>
#include <string>

int main() {
    int i = 42;
    std::string s = "hello";
    std::cout << std::vformat("Number: {}, Word: {}", std::make_format_args(i, s)) << '\n';

    return 0;
}

存储参数集合(需复用场景)

如果确实需要存储参数集合以便后续复用,应使用std::format_args_store,它会保存参数的副本或必要的包装对象,避免引用悬空:

#include <format>
#include <iostream>
#include <string>

int main() {
    int i = 42;
    std::string s = "hello";
    auto args_store = std::make_format_args_store<std::format_context>(i, s);
    std::format_args args = args_store.get();
    std::cout << std::vformat("Number: {}, Word: {}", args) << '\n';

    return 0;
}

内容的提问来源于stack exchange,提问作者Jonathan Geisler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 20:12:32