abi :: __cxa_demangle — почему буфер должен быть `malloc`-ed?

Документация 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. Почему возвращается другой указатель, когда выходной буфер уже пройден?

Под влиянием примера трассировка (), Я бы представил API как

// 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);

0

Решение

1) Почему выходной буфер в стеке не разрешен?

По предоставленной вами ссылке. If output_buffer is not long enough, it is expanded using realloc, Изменение размера данных в стеке невозможно, поскольку кадр стека обычно имеет фиксированный размер (особый случай alloca)

2) Почему возвращается другой указатель, когда выходной буфер уже пройден?

Когда используется realloc, нет причин думать, что вы получите тот же указатель. Например, если в этом месте недостаточно непрерывной свободной памяти, операционная система должна будет выделить память где-то еще.

Если бы мне пришлось угадывать, почему API был разработан таким образом, было бы неплохо не выделять память в функции, а затем возвращать ссылки на эту память. Вместо этого возьмите на себя ответственность вызывающего абонента как за распределение, так и за освобождение. Это помогает избежать непредвиденных утечек памяти и позволяет пользователю API разрабатывать свои собственные схемы выделения памяти. Я ценю такие вещи, потому что это позволяет пользователю использовать свои собственные схемы управления памятью, чтобы избежать таких вещей, как фрагментация памяти. Потенциальное использование realloc Хотя это немного портит эту идею, но вы, вероятно, можете обойти это, выделив достаточно большие блоки для выходного параметра, чтобы realloc никогда не называется.

3

Другие решения

  1. Почему выходной буфер в стеке не разрешен?
  2. Почему возвращается другой указатель, когда выходной буфер уже пройден?

Потому что имена классов с ++ могут быть произвольно длинными.

Попробуй это:

#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...
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector