abseil-cpp

库

abseil/abseil-cpp

Abseil 是谷歌开源的 C++ 通用库,扩展 C++ 标准库。

项目简介

Abseil 是谷歌从其内部代码库中提取并开源的一套 C++ 通用库,经过生产环境广泛测试。它提供了标准库缺失的组件,如字符串处理、容器和同步原语,旨在作为 C++ 项目的基础依赖。

README 预览

# Abseil - C++ Common Libraries\n\nThe repository contains the Abseil C++ library code. Abseil is an open-source\ncollection of C++ code (compliant to C++17) designed to augment the C++\nstandard library.\n\n## Table of Contents\n\n- [About Abseil](#about)\n- [Quickstart](#quickstart)\n- [Building Abseil](#build)\n- [Support](#support)\n- [Codemap](#codemap)\n- [Releases](#releases)\n- [License](#license)\n- [Links](#links)\n\n\n## About Abseil\n\nAbseil is an open-source collection of C++ library code designed to augment\nthe C++ standard library. The Abseil library code is collected from Google's\nown C++ code base, has been extensively tested and used in production, and\nis the same code we depend on in our daily coding lives.\n\nIn some cases, Abseil provides pieces missing from the C++ standard; in\nothers, Abseil provides alternatives to the standard for special needs\nwe've found through usage in the Google code base. We denote those cases\nclearly within the library code we provide you.\n\nAbseil is not meant to be a competitor to the standard library; we've\njust found that many of these utilities serve a purpose within our code\nbase, and we now want to provide those resources to the C++ community as\na whole.\n\n\n## Quickstart\n\nIf you want to just get started, make sure you at least run through the\n[Abseil Quickstart](https://abseil.io/docs/cpp/quickstart). The Quickstart\ncontains information about setting up your development environment, downloading\nthe Abseil code, running tests, and getting a simple binary working.\n\n\n## Building Abseil\n\n[Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official\nbuild systems for Abseil.\nSee the [quickstart](https://abseil.io/docs/cpp/quickstart) for more information\non building Abseil using the Bazel build system.\nIf you require CMake support, please check the [CMake build\ninstructions](CMake/README.md) and [CMake\nQuickstart](https://abseil.io/docs/cpp/quickstart-cmake).\n\n\n## Supp

常见问题 (5)

故障排除
如何修复在空的 Cord 上调用 SetExpectedChecksum() 之后,追加或前置添加大型 std::string 时发生的 absl::Cord 崩溃问题?

此问题影响带有预期校验和的空 absl::Cord:在追加/前插 512 字节或更大的右值 std::string 时会触发。启用断言的构建会在 IsDataEdge() 中因 edge != nullptr 断言失败;NDEBUG 构建可能会发生段错误。511 字节或更小的字符串工作正常。

在 absl/strings/cord.cc 中应用上游修复:在两个右值重载中,于创建大字符串树之前移除空的 CRC 节点:

// 在 Cord::Append(T&& src) 中,位于 src.size() > 511 的 else 分支内:
contents_.MaybeRemoveEmptyCrcNode();
CordRep* rep = CordRepFromString(std::forward<T>(src));
contents_.AppendTree(rep, CordzUpdateTracker::kAppendString);

// 在 Cord::Prepend(T&& src) 中,位于对应的 else 分支内:
contents_.MaybeRemoveEmptyCrcNode();
CordRep* rep = CordRepFromString(std::forward<T>(src));
contents_.PrependTree(rep, CordzUpdateTracker::kPrependString);

然后重新构建 Abseil 以及你的项目。在补丁版本可用之前,可通过以下方式规避该 bug:在初始数据添加之后再调用 SetExpectedChecksum();将首次追加/前插保持在 511 字节或更小;或者使用 absl::string_view 的 append/prepend 路径,而不是大右值 std::string 路径。

来源 Issue #2167
故障排除
如何修复在使用不相等的 PMR 分配器进行移动赋值后,absl::linked_hash_set 出现 heap-use-after-free 或 linked_hash_map 出现编译错误的问题?

当移动赋值所使用的分配器不会传播且比较结果不相等时,就会发生这种情况。std::list 会使用目标分配器重新创建其节点,但 linked_hash_set 内部的迭代器索引仍然指向源节点,而这些源节点随后会被释放。linked_hash_map 也可能无法编译,因为对 std::pair<const K, V> 进行元素赋值是非良构的。

修复方法:将 Abseil 更新到包含提交 d5c2f53dfc56c6d0d65a93a5e303c16a046e5fe6 的版本,或者应用该补丁并重新构建。

临时解决方法:
- 确保两个容器使用比较结果相等的分配器,例如同一个 std::pmr::memory_resource:

Set a{Alloc(&resource)};
Set b{Alloc(&resource)}; // same resource
b = std::move(a);        // safe

- 避免在不相等且不传播的分配器之间进行移动赋值;改为重新构建目标容器:
b.clear();
for (const auto& x : a) b.insert(x);
a.clear();

对于 linked_hash_map,将每个键/值对插入目标容器。使用 AddressSanitizer 重新构建,以验证 heap-use-after-free 已消失。

来源 Issue #2174
故障排除
如何修复在为 arm-none-eabi 或裸机 ELF 构建时出现的 Abseil "fatal error: link.h: No such file or directory" 错误?

此问题出现在 Abseil 提交 71330b9 上,因为 ABSL_HAVE_ELF_MEM_IMAGE 对每个 __ELF__ 目标都会被启用,但诸如使用 newlib 的 arm-none-eabi-g++ 之类的裸机工具链会生成 ELF 目标文件,却并不附带 glibc 的 <link.h>。

临时解决方法:编辑 absl/debugging/internal/elf_mem_image.h,在现有的用于定义 ABSL_HAVE_ELF_MEM_IMAGE 的 #if 中添加对 <link.h> 可用性的检查:

!defined(__XTENSA__) && __has_include(<link.h>)

例如,该条件应以如下内容结尾:

#if defined(__ELF__) &&
    // ...existing deny-list checks...
    !defined(__XTENSA__) && __has_include(<link.h>)
#define ABSL_HAVE_ELF_MEM_IMAGE 1
#endif

这样仅当所需头文件缺失时才会禁用 ELF 内存映像支持。__has_include 在 C++17 下可用,并且已在 Abseil 的其他地方使用。

使用以下命令验证:

arm-none-eabi-g++ -std=c++17 -I. -fsyntax-only absl/debugging/internal/elf_mem_image.cc
arm-none-eabi-g++ -std=c++17 -I. -fsyntax-only absl/debugging/internal/vdso_support.cc

上游的修复可能会改为在 <link.h> 不可用时使用 <elf.h> 并在本地定义 ElfW,从而保持该支持处于启用状态,因此在有可用的已修复 Abseil 版本时,建议优先更新到该版本。

来源 Issue #2153
故障排除
如何修复在 Windows 上使用 CMake 构建 Abseil DLL 时出现的 "'crc_cpu_detect' 目标未找到" 错误?

在 Windows 上使用 MSVC/CMake 将 Abseil v20260817.0 构建为 DLL 时会出现此错误:CMake/AbseilDll.cmake 文件仍然引用了已被移除的 crc_cpu_detect 构建目标,该目标已在 absl/base/CMakeLists.txt 中被替换为 base_cpu_detect。请按以下步骤手动修复:1. 打开 Abseil 源码目录中的 CMake/AbseilDll.cmake,定位到大约第 548 行。2. 将对 crc_cpu_detect 的引用替换为 base_cpu_detect。3. 重新运行 CMake 配置命令并重新构建项目。

来源 Issue #2139
故障排除
如何修复在为 arm-none-eabi/newlib 构建 Abseil 时出现的 'EncodeVarint' 重载不明确(二义性)错误?

这是 Abseil issue #2148。在诸如 arm-none-eabi 的 newlib 目标平台上,int32_t 是 long int,而不是普通的 int,因此 int 类型的实参无法与任何 EncodeVarint 重载精确匹配。bool 类型的实参也可能产生歧义。请将 Abseil 更新到包含该修复的修订版本,或者在 absl/log/internal/proto.h 中添加显式的 int 和 bool 重载,让它们转发到定宽重载:

bool EncodeVarint(uint64_t field_number, int value,
                  absl::Span<char>* buf) {
  return EncodeVarint(field_number, static_cast<int32_t>(value), buf);
}

bool EncodeVarint(uint64_t field_number, bool value,
                  absl::Span<char>* buf) {
  return EncodeVarint(field_number, static_cast<uint64_t>(value), buf);
}

如果现有函数仅在头文件中声明,请添加相应的声明,并将转发定义放在 proto.cc 中。等效的变通方法是在调用点将 source_line() 强制转换为 int32_t,并在编码前将 bool 值显式强制转换为 uint64_t。例如,使用以下命令重新构建:

arm-none-eabi-g++ -std=c++17 -I. -fsyntax-only \
  absl/log/internal/structured_proto.cc \
  absl/log/internal/log_message.cc

来源 Issue #2148