abi :: __ cxa_demangle - 为什么缓冲区必须是`malloc`-ed?

时间:2017-07-10 22:17:00

标签: c++ api abi demangler

abi::__cxa_demangle的文档(例如https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html)指定第二个参数char * output_buffer需要malloc - ed。

这意味着不允许在堆栈上分配的字符缓冲区,如下所示。

  enum {N = 256};
  char output_buffer[N];
  size_t output_length = 0;
  int status = -4;
  char * const result = std::__cxa_demangle(mangled_name,
                        output_buffer, &output_length, &status);

两个问题:

  1. 为什么不允许堆叠output_buffer

  2. 为什么在输出缓冲区已经传递时会返回不同的指针?

  3. backtrace()示例影响,我想象一下如下的

    // Demangle the symbol in 'mangled_name' and store the output
    // in 'output_buffer' where 'output_buffer' is a caller supplied
    // buffer of length 'output_buffer_length'. The API returns the 
    // number of bytes written to 'output_buffer' which is not
    // greater than 'output_buffer_length'; if it is
    // equal to 'output_buffer_length', then output may have been
    // truncated.
    size_t mydemangle(char const * const mangled_name,
                      char * output_buffer,
                      size_t const output_buffer_length);
    

2 个答案:

答案 0 :(得分:4)

1)为什么堆栈上的output_buffer不被允许?

从您提供的链接。 If output_buffer is not long enough, it is expanded using realloc。由于堆栈帧通常具有固定大小(特殊情况alloca

,因此无法在堆栈上调整数据大小

2)为什么在输出缓冲区已经传递时会返回不同的指针?

当使用realloc时,没有理由认为你会得到相同的指针。例如,如果该位置没有足够的连续内存,则操作系统需要在其他位置分配内存。

如果我不得不猜测为什么API是这样设计的,那么通常认为不在函数中分配内存然后返回对该内存的引用通常是好习惯。相反,让调用者负责分配和释放。这有助于避免意外的内存泄漏,并允许API的用户设计自己的内存分配方案。我很欣赏这样的东西,因为它允许用户利用自己的内存管理方案来避免内存碎片等问题。虽然realloc有可能使用这种想法,但是你可以通过为输出参数分配足够大的块来解决这个问题,以便永远不会调用realloc

答案 1 :(得分:0)

  
      
  1. 为什么堆栈上的output_buffer不被允许?
  2.   
  3. 为什么在传输输出缓冲区时返回了不同的指针?
  4.   

因为c ++类名可以任意长。

试试这个:

#include <iostream>
#include <cxxabi.h>
#include <utility>

using foo = std::make_index_sequence<10000>;

int main()
{
    size_t buff_size = 128;
    auto buff = reinterpret_cast<char*>(std::malloc(buff_size));
    std::cout << "buffer before: " << static_cast<void*>(buff) << std::endl;
    int stat = 0;
    buff = abi::__cxa_demangle(typeid(foo).name(), buff, &buff_size, &stat);
    std::cout << "buffer after: " << static_cast<void*>(buff) << std::endl;
    std::cout << "class name: " << buff << std::endl;
    std::free(buff);
}

示例输出:

buffer before: 0x7f813d402850
buffer after: 0x7f813e000000
class name: std::__1::integer_sequence<unsigned long, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 8ul, 9ul, 10ul, 11ul, 12ul, 13ul, 14ul, 15ul, 16ul, 17ul, ... and so on...