当 filesystem::path 被破坏时程序崩溃

2024-03-03

以下程序崩溃:

#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
    fs::path p1 = "/usr/lib/sendmail.cf";
 
    std::cout << "p1 = " << p1 << '\n';
}

汇编:

$ g++ -std=c++17 pathExistsTest.cpp
$ ./a.out 
p1 = "/usr/lib/sendmail.cf"
[1]    35688 segmentation fault (core dumped)  ./a.out

在Ubuntu 20.04上测试,编译器是GCC 8.4.0。

Valgrind,这是剪切输出:

==30078==    by 0x4AE5034: QAbstractButton::mouseReleaseEvent(QMouseEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.8)
==30078==    by 0x4A312B5: QWidget::event(QEvent*) (in /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5.12.8)
==30078==  Address 0x2b is not stack'd, malloc'd or (recently) free'd
==30078== 
==30078== 
==30078== Process terminating with default action of signal 11 (SIGSEGV)
==30078==  Access not within mapped region at address 0x2B
==30078==    at 0x13AD9B: std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector() (in /home/(me)/src/tomato/build-src-Desktop-Release/TomatoLauncher)

全输出 https://pastebin.com/gAv4Tec5
我什至不知道为什么调用向量dtor?我只创建一个path变量,无vector<path>.


TL;DR

您正在使用 GCC 8.4.0 进行编译,因此您需要显式链接-lstdc++fs.

由于您使用的是 GCC 8.4.0,因此您使用的是 GCC 8.4.0 版本的 GNU C++ 标准库(又名 libstdc++ 标头)。但是你的系统(Ubuntu 20.04)只包含libstdc++.so.6.0.28来自 GCC 9。如果您没有明确链接-lstdc++fs,那么你不小心消耗了std::filesystemGCC 9 中的符号(通过libstdc++.so)而不是 GCC 8(通过libstdc++fs.a).

GCC 8 和 GCC 9 不兼容std::filesystem类型。更具体地说,它们的二进制布局是不同的。这基本上是一种非常隐蔽的 ODR 违规行为。您的对象已分配给 GCC 8 布局,但使用 GCC 9 布局构建。当您尝试销毁它时,析构函数使用 GCC 8 布局并崩溃,因为数据不是它所期望的。


有两段代码使用不同的、不兼容的布局path type.

第一段代码来自libstdc++.so.6.0.28:它包含一个定义path::_M_split_cmpts(),通过内联构造函数调用path::path(string_type&&, format)。由于构造函数是内联的,因此构造函数本身的代码会生成到可执行文件中。因此,您的可执行文件包含对path::_M_split_cmpts.

第二段代码位于您自己的可执行文件中:它生成内联(默认)析构函数的指令path::~path(),以及它调用的内联函数;一直到std::filesystem::__cxx11::path::path<char [21], std::filesystem::__cxx11::path>(char const (&) [21], std::filesystem::__cxx11::path::path>(char const (&) [21], std::filesystem::__cxx11::path::format).


我们怎样才能找到这个呢?

使用调试器: 遍历 ctor 中的可疑函数可以发现:

0x5569716498ed <std::filesystem::__cxx11::path::path<char [21], std::filesystem::__cxx11::path>(char const (&) [21], std::filesystem::__cxx11::path::path>(char const (&) [21], std::filesystem::__cxx11::path::format)+112>       callq  0x5569716491e0 <_ZNSt10filesystem7__cxx114path14_M_split_cmptsEv@plt>

这是通过 PLT 的调用(因此,可能来自共享对象,并且绝对不是内联的)。我们进入其中并:

(gdb) bt
#0  0x00007f102c60f260 in std::filesystem::__cxx11::path::_M_split_cmpts() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00005569716498ed in std::filesystem::__cxx11::path::path<char [21], std::filesystem::__cxx11::path> (this=0x7ffe1a07ad60, __source=...)
    at /usr/include/c++/8/bits/fs_path.h:185
#2  0x00005569716493fd in main () at blub.cpp:6

所以,我们可以看出,它确实来自/lib/x86_64-linux-gnu/libstdc++.so.6,这是一个符号链接/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28.

我们可以看到例如 dtor在OP的Valgrind输出中:

==30078== Invalid read of size 8
==30078==    at 0x13AD9B: std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector() (in /home/(me)/src/tomato/build-src-Desktop-Release/TomatoLauncher)

它是内联的,因此位于可执行文件中。


现在,真正有趣的部分是包含内联函数的标头pathpath::_M_split_cmpts函数来自 GNU C++ 标准库 (libstdc++)。

他们怎么能不兼容呢?

为了回答这个问题,我们来看看确切的版本。我们正在使用 GCC 8.4.0 进行编译。它已包含在包含路径中,它们引用 Ubuntu 20.04 的 gcc-8 包中附带的标准库标头。它们完美匹配,您必须更改默认设置才能使 GCC 使用不同的、不匹配的标准库标头。因此,标头是 GCC 8.4.0 的标头。

那么共享对象呢libstdc++.so?我们正在与libstdc++.so.6.0.28根据ldd和调试器。根据libstdc++ ABI 政策和指南 https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html, 那是海湾合作委员会 >= 9.3.

libstdc++.so.6.0.28 确实包含以下定义_ZNSt10filesystem7__cxx114path14_M_split_cmptsEv:

$ objdump -T /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28 | grep _ZNSt10filesystem7__cxx114path14_M_split_cmptsEv
000000000016a260 g    DF .text  00000000000005f3  GLIBCXX_3.4.26 _ZNSt10filesystem7__cxx114path14_M_split_cmptsEv

根据 ABI 文档,这是

GCC 9.1.0:GLIBCXX_3.4.26、CXXABI_1.3.12

所以这个符号在 GCC 8.4.0 中不可用。


为什么编译器/链接器不抱怨?

当我们使用 gcc-8 进行编译时,为什么编译器或链接器不会抱怨我们使用了 GCC 9 中的符号?

如果我们编译-v,我们看到链接器调用:

COLLECT_GCC_OPTIONS='-v' '-std=c++17' '-g' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-linux-gnu/8/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/8/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper -plugin-opt=-fresolution=/tmp/cceJgWPt.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/8/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/8 -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/8/../../.. /tmp/ccTNph3u.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/8/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crtn.o                           COLLECT_GCC_OPTIONS='-v' '-std=c++17' '-g' '-shared-libgcc' '-mtune=generic' '-march=x86-64'

在那里,我们有-L/usr/lib/gcc/x86_64-linux-gnu/8以及查找标准库的其他路径。在那里,我们发现libstdc++.so -> ../../../x86_64-linux-gnu/libstdc++.so.6,最终指向/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28 (!!!).

所以链接器被赋予了 GCC 9libstdc++.so,并且它不会从编译器接收有关该符号的任何版本信息 (*)。编译器只知道源代码,而源代码也知道在这种情况下不包含符号版本(GCC 8.4.0 的文件系统头)。然而,符号版本存在于 ELF 二进制文件中libstdc++.so。链接器看到GLIBCXX_3.4.26对于编译器请求的符号_ZNSt10filesystem7__cxx114path14_M_split_cmptsEv并对此感到满意。让您想知道是否有一个链接器开关来告诉链接器“如果我请求未版本化的符号,则不要使用版本化的符号”。

(*) 链接器不会从编译器接收有关未解析符号的任何符号信息,因为编译器没有来自源代码的此类信息。你可以将信息添加到您的源代码中 https://stackoverflow.com/a/2858996/420683。我不知道 libstdc++ 通常是如何做到的 - 或者它对头文件中符号版本的策略。看起来根本没有完成filesystem.

ELF 符号版本控制机制通常应该防止此类不兼容性:如果存在布局不兼容的更改,则创建一个具有相同名称但版本不同的新符号,并且add it to libstdc++.so,然后包含旧版本和新版本。

编译的二进制文件libstdc++.so指定它想要的符号的版本,并且动态加载器根据匹配名称和版本的符号正确解析未定义的符号。请注意,动态链接器确实不知道要搜索哪个共享库(在 Windows/PE 上,这是不同的)。任何“符号请求”只是一个未定义的符号,并且有一个完全独立的所需库列表,它们应提供这些未定义的符号。但是二进制文件中没有映射哪个符号应该来自哪个库。

因为 ELF 符号版本控制机制允许向后兼容的符号添加,所以我们可以维护single libstdc++.so for multiple编译器的版本。这就是为什么您会在各处看到符号链接,将所有符号链接都指向同一个文件。后缀.6.0.28是另一种正交版本控制方案,它允许向后-不相容更改:您的二进制文件可以指定它需要libstdc++.so.6你可以添加一个不兼容的libstdc++.so.7对于其他二进制文件。

Fun fact:如果您将库链接到纯 GCC 8 版本libstdc++.so,你会看到链接器错误 https://godbolt.org/#g:!((g:!((g:!((g:!((h:codeEditor,i:(fontScale:14,j:1,lang:c%2B%2B,selection:(endColumn:2,endLineNumber:9,positionColumn:2,positionLineNumber:9,selectionStartColumn:2,selectionStartLineNumber:9,startColumn:2,startLineNumber:9),source:%27%23include+%3Ciostream%3E%0A%23include+%3Cfilesystem%3E%0Anamespace+fs+%3D+std::filesystem%3B%0Aint+main()%0A%7B%0A++++fs::path+p1+%3D+%22/usr/lib/sendmail.cf%22%3B+//+portable+format%0A+%0A++++std::cout+%3C%3C+%22p1+%3D+%22+%3C%3C+p1+%3C%3C+!%27%5Cn!%27%3B%0A%7D%27),l:%275%27,n:%270%27,o:%27C%2B%2B+source+%231%27,t:%270%27)),k:50,l:%274%27,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((h:compiler,i:(compiler:g83,filters:(b:%270%27,binary:%271%27,commentOnly:%270%27,demangle:%270%27,directives:%270%27,execute:%270%27,intel:%270%27,libraryCode:%271%27,trim:%271%27),fontScale:14,j:1,lang:c%2B%2B,libs:!(),options:%27-std%3Dc%2B%2B17+-Wall+-Wextra+-pedantic%27,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:%275%27,n:%270%27,o:%27x86-64+gcc+8.3+(Editor+%231,+Compiler+%231)+C%2B%2B%27,t:%270%27)),k:50,l:%274%27,m:100,n:%270%27,o:%27%27,s:0,t:%270%27)),l:%272%27,m:60.79136690647482,n:%270%27,o:%27%27,t:%270%27),(g:!((h:output,i:(compiler:1,editor:1,fontScale:14,wrap:%271%27),l:%275%27,n:%270%27,o:%27%231+with+x86-64+gcc+8.3%27,t:%270%27)),header:(),l:%274%27,m:39.20863309352518,n:%270%27,o:%27%27,s:0,t:%270%27)),l:%273%27,n:%270%27,o:%27%27,t:%270%27)),version:4。链接共享库对二进制文件没有多大作用;但是,它确实修复了未解析符号的符号版本,并且可以检查在查看所有库后是否没有留下未解析的符号。我们可以看到你的二进制文件实际上请求_ZNSt10filesystem7__cxx114path14_M_split_cmptsEv@GLIBCXX_3.4.26当你将它链接到libstdc++.so.6.0.28.

有趣的事实 2:如果您针对纯 GCC 8 版本运行您的库libstdc++.so,您会收到动态链接器错误,因为它找不到_ZNSt10filesystem7__cxx114path14_M_split_cmptsEv@GLIBCXX_3.4.26.


实际上应该发生什么?

你实际上应该链接到libstdc++fs.a。它还提供了一个定义_ZNSt10filesystem7__cxx114path14_M_split_cmptsEv,它不是符号链接,而是特定于此 GCC 版本的:/usr/lib/gcc/x86_64-linux-gnu/8/libstdc++fs.a.

当您链接到-lstdc++fs,您可以将其符号直接包含到可执行文件中(因为它是静态库)。可执行文件中的符号优先于共享对象中的符号。因此,_ZNSt10filesystem7__cxx114path14_M_split_cmptsEv from libstdc++fs.a用来。


实际上布局不兼容是什么path?

GCC 9 引入了一种不同的类型来保存路径的组件。使用clang++ -cc1 -fdump-record-layouts,我们可以在左侧看到偏移量,在右侧看到成员和类型名称:

海湾合作委员会 8.4.0:

 0 | class std::filesystem::__cxx11::path
 0 |   class std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> > _M_pathname
 0 |     struct std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::_Alloc_hider _M_dataplus
 0 |       class std::allocator<char> (base) (empty)
 0 |         class __gnu_cxx::new_allocator<char> (base) (empty)
 0 |       std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::pointer _M_p
 8 |     std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::size_type _M_string_length
16 |     union std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::(anonymous at /usr/include/c++/8/bits/basic_string.h:160:7) 
16 |       char [16] _M_local_buf
16 |       std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::size_type _M_allocated_capacity
32 |   class std::vector<struct std::filesystem::__cxx11::path::_Cmpt, class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt> > _M_cmpts
32 |     struct std::_Vector_base<struct std::filesystem::__cxx11::path::_Cmpt, class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt> > (base)
32 |       struct std::_Vector_base<struct std::filesystem::__cxx11::path::_Cmpt, class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt> >::_Vector_impl _M_impl
32 |         class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt> (base) (empty)
32 |           class __gnu_cxx::new_allocator<struct std::filesystem::__cxx11::path::_Cmpt> (base) (empty)
32 |         std::_Vector_base<struct std::filesystem::__cxx11::path::_Cmpt, class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt> >::pointer _M_start
40 |         std::_Vector_base<struct std::filesystem::__cxx11::path::_Cmpt, class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt> >::pointer _M_finish
48 |         std::_Vector_base<struct std::filesystem::__cxx11::path::_Cmpt, class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt> >::pointer _M_end_of_storage
56 |   enum std::filesystem::__cxx11::path::_Type _M_type
   | [sizeof=64, dsize=57, align=8,
   |  nvsize=57, nvalign=8]

海湾合作委员会 9.3.0:

 0 | class std::filesystem::__cxx11::path
 0 |   class std::__cxx11::basic_string<char> _M_pathname
 0 |     struct std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::_Alloc_hider _M_dataplus
 0 |       class std::allocator<char> (base) (empty)
 0 |         class __gnu_cxx::new_allocator<char> (base) (empty)
 0 |       std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::pointer _M_p
 8 |     std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::size_type _M_string_length
16 |     union std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::(anonymous at /usr/include/c++/9/bits/basic_string.h:171:7) 
16 |       char [16] _M_local_buf
16 |       std::__cxx11::basic_string<char, struct std::char_traits<char>, class std::allocator<char> >::size_type _M_allocated_capacity
32 |   struct std::filesystem::__cxx11::path::_List _M_cmpts
32 |     class std::unique_ptr<struct std::filesystem::__cxx11::path::_List::_Impl, struct std::filesystem::__cxx11::path::_List::_Impl_deleter> _M_impl
32 |       class std::__uniq_ptr_impl<struct std::filesystem::__cxx11::path::_List::_Impl, struct std::filesystem::__cxx11::path::_List::_Impl_deleter> _M_t
32 |         class std::tuple<struct std::filesystem::__cxx11::path::_List::_Impl *, struct std::filesystem::__cxx11::path::_List::_Impl_deleter> _M_t
32 |           struct std::_Tuple_impl<0, struct std::filesystem::__cxx11::path::_List::_Impl *, struct std::filesystem::__cxx11::path::_List::_Impl_deleter> (base)
32 |             struct std::_Tuple_impl<1, struct std::filesystem::__cxx11::path::_List::_Impl_deleter> (base) (empty)
32 |               struct std::_Head_base<1, struct std::filesystem::__cxx11::path::_List::_Impl_deleter, true> (base) (empty)
32 |                 struct std::filesystem::__cxx11::path::_List::_Impl_deleter (base) (empty)
32 |             struct std::_Head_base<0, struct std::filesystem::__cxx11::path::_List::_Impl *, false> (base)
32 |               struct std::filesystem::__cxx11::path::_List::_Impl * _M_head_impl
   | [sizeof=40, dsize=40, align=8,
   |  nvsize=40, nvalign=8]

区别在于path::_M_cmpts:

// GCC 8
class std::vector<
  struct std::filesystem::__cxx11::path::_Cmpt,
  class std::allocator<struct std::filesystem::__cxx11::path::_Cmpt>
> _M_cmpts

// GCC 9
struct std::filesystem::__cxx11::path::_List _M_cmpts

您还可以看到以下结构path::_List在上面的记录转储中。它与 GCC 8 非常不兼容vector.

请记住我们正在打电话path::_M_split_cmpts通过 GCC 9 的 libstdc++.so,我们崩溃了vector析构函数为此_M_cmpts数据成员。

这是更改自的提交vector to _List:

commit 4f87bb8d6e8dec21a07f1fba641a78a127281349
Author: Jonathan Wakely <[email protected] /cdn-cgi/l/email-protection>
Date:   Thu Dec 13 20:33:55 2018 +0000

PR libstdc++/71044 optimize std::filesystem::path construction

This new implementation has a smaller footprint than the previous
implementation, due to replacing std::vector<_Cmpt> with a custom pimpl
type that only needs a single pointer. The _M_type enumeration is also
combined with the pimpl type, by using a tagged pointer, reducing
sizeof(path) further still.

Construction and modification of paths is now done more efficiently, by
splitting the input into a stack-based buffer of string_view objects
instead of a dynamically-allocated vector containing strings. Once the
final size is known only a single allocation is needed to reserve space
for it.  The append and concat operations no longer require constructing
temporary path objects, nor re-parsing the entire native pathname.
This results in algorithmic improvements to path construction, and
working with large paths is much faster.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当 filesystem::path 被破坏时程序崩溃 的相关文章

随机推荐

  • 如何关闭selenium运行时弹出的窗口?

    我想关闭弹出窗口 已知窗口名称 然后返回到原始窗口 我该怎么办 如果我无法获得窗口中关闭按钮的常量 那么有什么一般行为可以达到目标吗 使用WebDriver 用Java显示 你可以做这样的事情 instantiate your driver
  • .NET 中“托管”资源与“非托管”资源是什么意思?

    NET 中术语托管资源和非托管资源是什么意思 他们是如何出现的 术语 非托管资源 通常用于描述某些事物不直接受垃圾收集器控制 例如 如果您打开到数据库服务器的连接 这将使用服务器上的资源 用于维护连接 以及客户端计算机上可能的其他非 net
  • Integer.Parse 与 CInt

    基本上这两个我都用过Integer Parse and CInt https msdn microsoft com en us library s2dy91zy aspx在我的大多数日常编程任务中 但我对两者之间的区别有点困惑 有什么区别I
  • 跨子域的 ASP.NET 身份 Cookie

    对于表单身份验证 我在 web config 中使用了它 注意域属性
  • 使用 golang.org/x/oauth2 进行 golang Facebook 身份验证

    我正在尝试使用以下方法编写一个简单的程序golang org x oauth2包裹 但我似乎无法用代码交换访问令牌 以下错误有点误导 因为它表示授权代码已被使用 但每次调用登录对话框时我都会看到一个新代码 我是 golang 新手 我可能会
  • 诊断“请求超时”HttpExceptions 有进展吗?

    我遇到了与这篇文章中描述的相同的问题 诊断 请求超时 HttpException https stackoverflow com questions 441792 diagnosing request timed out httpexcep
  • 如何在 jqGrid 处理之前更改从服务器接收的数据

    我想要实现的场景 我从服务器检索一些数据 我循环数据并添加 更改某些字段的值 数据显示在网格中 用户在本地编辑数据 完成后 用户将整个网格数据提交到服务器 我如何尝试实现它 我做了一个 jqGridloadonce true editurl
  • 按优先级和组值对结果进行排序,然后过滤结果

    这是我的 DynamoDB 当前数据 我的目标是创建一个查询 该查询过滤组集中的结果 类似于 默认 然后按优先级排序 然后将结果过滤到loggedIn true和status idle的结果 在 SQL 中它会是这样的 SELECT FRO
  • 如何使用 JavaScript 防止屏幕休眠

    我有一个用例 我们不希望正在进行测试的用户在测试时睡眠超时 即 3 小时 我正在查看 nosleep js 但我遇到了 cpu 过度使用问题 因为它在 Windows 中无法工作 我想知道考试应用程序是如何做到这一点的 以及 YouTube
  • 如何在詹金斯中替换摩卡UTF8复选标记符号

    当我在詹金斯中运行摩卡测试时 在控制台输出上我可以看到 而不是 检查标记 utf 8 字符 如何将这些符号替换为人类可读的格式 修改默认报告者 最简单的方法 修改默认报告者 https github com mochajs mocha bl
  • 如何在 Java 中对 Hive 进行异步调用?

    我想以异步方式在服务器上执行 Hive 查询 Hive 查询可能需要很长时间才能完成 因此我不想阻止调用 我目前正在使用 Thirft 进行阻塞调用 在 client execute 上阻塞 但我还没有看到如何进行非阻塞调用的示例 这是阻止
  • 图片来自流问题

    我在从流创建图像时遇到问题 在我的 Windows 电脑上 它分叉得很好 在 ubuntu 服务器上 它抛出一个错误 System ArgumentException A null reference or invalid value wa
  • WPF MenuItem.Icon 尺寸

    所以我有一个 MenuItem 在 ContextMenu 中 如果它确实有影响 我不认为它有影响 我想使用 MenuItem Icon 属性在 MenuItem 中显示图标 下面是执行此操作的 XAML 代码
  • HttpClient PCL Cookie 未应用于请求

    我使用 NET HttpClient for PCL 2 2 15 作为跨 Windows Phone 8 Windows 8 和 NET 4 5 的通用库 但是 我没有看到 cookie 被应用于请求 我使用以下代码设置 HttpClie
  • 这段代码是什么意思“ofstream fout(getenv("OUTPUT_PATH"));”

    我对 cpp 还是个新手 如果有人能帮助我理解这行代码 我将不胜感激 ofstream fout getenv OUTPUT PATH 这段代码我几乎看到了每一个 Hackerrank 挑战 这段代码的目的是什么 我说 当有疑问时 简化 当
  • ListView 滚动混乱

    我扩展了基本适配器 我遇到了一些奇怪的问题 当我滚动此列表视图时 我的最后一个项目被第一个项目替换 下次当我滚动时 另一个项目等等 有时它是正确的 为什么这段代码会发生这种情况 Override public View getView fi
  • 如何让 DataAnnotations 在 asp.net 4.5 WebForms 中工作?

    我正在使用带有模型绑定和实体框架 5 的 net 4 5 WebForms 我的网络表单的一部分
  • Invoke-ASCmd :身份验证失败:用户界面不可用时需要用户 ID 和密码

    我正在尝试使用 Azure DevOps 通过 CICD 刷新 已 部署的表格模型的凭据 利用调用ASCmd在 PowerShell 中刷新凭据 当我提供租户 ID 应用程序 ID 和密钥时 该脚本在本地运行良好 但是 当我从 Azure
  • 无法构建:如何为新模块添加 Android 构建配置

    现在我正在将我的 Android 代码转换为模块化架构方法 尝试从 聊天 模块添加对 应用程序 模块的依赖项时遇到问题 我有以下 app 模块的构建配置 android lintOptions checkReleaseBuilds fals
  • 当 filesystem::path 被破坏时程序崩溃

    以下程序崩溃 include