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

使用ltrace追踪时,std::string分配1KB内存的malloc/new调用在哪?

问题:std::string堆内存分配的malloc/new调用为何未在ltrace中显示?

测试代码

#include <thread>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <string>
#include <iostream>

int main()
{
    std::string buf(1024, 'a');
    std::cout << buf << '\0';
    return 0;
}

编译执行命令

g++ -O0 main.cpp && ltrace -n3 -fS ./a.out

ltrace输出

[pid 25689] SYS_mprotect(0x7f02e5293000, 4096, 1, 0x7f02e5294030) = 0
[pid 25689] SYS_brk(0, 0x7f02e46d3b20, 0x7f02e46d3b78, 0x7f02e46d3b78) = 0xb00000
[pid 25689] SYS_brk(0xb33000, 0x7f02e46d3b20, 0xb00000, 0x7f02e46d3b78) = 0xb33000
[pid 25689] __libc_start_main(0x400a22, 1, 0x7ffeeb3a1338, 0x400b80 <unfinished ...>
[pid 25689]    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_local_data()(0x7ffeeb3a1210, 1024, 97, 0x7ffeeb3a1237) = 0x7ffeeb3a1220
[pid 25689]    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider::_Alloc_hider(char*, std::allocator<char> const&)(0x7ffeeb3a1210, 0x7ffeeb3a1220, 0x7ffeeb3a1237, 0x7ffeeb3a1220) = 0x7ffeeb3a1237
[pid 25689]    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct(unsigned long, char)(0x7ffeeb3a1210, 1024, 97, 1024) = 1024
[pid 25689]    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)(0x6012c0, 0x7ffeeb3a1210, 0xb12400, 0xb12400 <unfinished ...>
[pid 25689]       SYS_fstat(1, 0x7ffeeb3a1040, 0x7ffeeb3a1040, 1) = 0
[pid 25689]    <... std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) resumed> ) = 0x6012c0
[pid 25689]    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)(0x6012c0, 0, 0x7f02e5064310, 0) = 0x6012c0
[pid 25689]    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(0x7ffeeb3a1210, 0x7f02e46d5780, 0x7f02e5064310, 0xb12831) = 1
[pid 25689]    SYS_write(1, 0xb12430, 1025, 88aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)  = 1025
[pid 25689]    SYS_exit_group(0, 60, 0, 2956 <no return ...>
[pid 25689] +++ exited (status 0) +++

疑问

分配1KB char内存的malloc和/或new调用在哪里?我曾怀疑它是在某个库调用(如_M_construct)内部执行而未被显示,但这个假设不成立,因为我能看到库调用内部的其他库调用。那么malloc/new调用究竟在哪里?我本以为会在std::string的构造函数中看到它。

注意:我知道string采用短缓冲区优化,但gcc中默认构造的std::string的本地容量为15(std::string str; std::cout << str.capacity() << '\n';),远小于1KB字符。因此这1KB的'a'必须被分配在堆上。


解答

核心原因

ltrace默认不会主动跟踪C++的operator new/operator delete,也不会自动展开std::allocator到malloc的调用链。你看到的SYS_brk是glibc内存分配器(ptmalloc)调整堆空间的系统调用,但ltrace默认只显示系统调用,没把上层的malloc调用展示出来。

验证方法

要看到malloc或operator new的调用,需要给ltrace添加指定跟踪函数的参数:

  1. 跟踪malloc调用:
ltrace -n3 -fS -e malloc ./a.out
  1. 跟踪所有库函数(包括malloc和operator new):
ltrace -n3 -f ./a.out

执行后就能看到std::string构造过程中触发的malloc/operator new调用了。

补充说明

std::string的内存分配是通过默认的std::allocator<char>完成的,allocator底层会调用malloc,但ltrace默认仅跟踪标准C库的公开函数和系统调用,不会自动关联allocator的内部调用。加上-e malloc参数后,ltrace会专门捕获malloc的调用,就能看到你预期的堆内存分配操作了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:03:10