Почему на большинстве платформ нет «align_realloc»? - PullRequest
3 голосов
/ 16 июня 2019

MSVC имеет свои нестандартные функции _aligned_malloc, _aligned_realloc и _aligned_free.

C ++ 17 и C11 представили (std::)aligned_alloc, результаты которого могут быть de , выделенными с free или realloc. Но realloc нельзя использовать для фактического re распределения памяти, возвращаемой aligned_alloc, так как он не принимает параметр alignment и, таким образом, не может гарантировать, что возвращаемый указатель будет правильно выровнен .

Я даже не могу найти никаких нестандартных расширений, которые могли бы перераспределить выровненную память (сохраняя ее выравнивание) на платформах, отличных от Microsoft Windows / Visual C ++.

Я неправильно искал или действительно нет альтернативы _aligned_realloc на POSIX и других платформах?

Если это так,

  1. Почему?
  2. Что можно использовать вместо этих платформ? Разве нет ничего лучше, чем вызвать aligned_alloc с новым выравниванием, а затем выполнить memcpy и free со старым указателем на успех?

Ответы [ 2 ]

5 голосов
/ 17 июня 2019

Хотя POSIX (который обычно выступает в качестве наименьшего общего знаменателя на большинстве платформ) не имеет aligned_realloc, он имеет aligned_alloc и memcpy. Следовательно, вы можете очень легко реализовать свой собственный aligned_realloc, который гарантированно будет работать на любой разумно совместимой платформе, использующей их. Однако обратите внимание, что не существует стандартного метода posix для получения размера malloc 'области памяти. Вам придется отслеживать это самостоятельно.

РЕДАКТИРОВАТЬ: есть немного свободного времени, поэтому я расширяю его, чтобы ответить на самую распространенную критику

То, что я предложил, это, как заметит проницательный комментатор, а не то, как realloc работает внутри.

Под капотом ваша стандартная реализация realloc сделает все возможное, чтобы не допустить преобразующего вышеописанного поведения неправильного использования памяти и последующего освобождения памяти. Он попытается использовать один из двух вариантов поведения, прежде чем прибегнуть к отступлению. 1) Если новый размер меньше старого, он изменит размер памяти на месте, избегая необходимости выделять, копировать или освобождать. 2) если новый размер больше старого, он (в упрощенном виде) увидит, есть ли рядом свободная память достаточного размера, и если это так, то сожрет эту память и изменит ее размер. Если нет, то он прибегает к запасному варианту.

Я предложил наивный подход, поскольку полагал, что большинство людей, задающих этот вопрос, не захотят реализовывать собственную реализацию malloc. (Хотя я настоятельно рекомендую делать это в образовательных целях)

Надеюсь, это удовлетворит любые жалобы!

2 голосов
/ 16 июня 2019

Библиотека Intel Math Kernel (бесплатно; доступно для Windows, Linux и macOS) ver.> = 11.3.1 имеет mkl_realloc, который сохраняет выравнивание:

Простой пример:

auto p1 = std::aligned_alloc(1024, 1000);
std::cout << reinterpret_cast<std::uintptr_t>(p1) % 1024 << std::endl;
auto p2 = std::realloc(p1, 2000);
std::cout << reinterpret_cast<std::uintptr_t>(p2) % 1024 << std::endl;
auto p3 = std::realloc(p2, 3000);
std::cout << reinterpret_cast<std::uintptr_t>(p3) % 1024 << std::endl;

auto q1 = mkl_malloc(1000, 1024);
std::cout << reinterpret_cast<std::uintptr_t>(q1) % 1024 << std::endl;
auto q2 = mkl_realloc(q1, 2000);
std::cout << reinterpret_cast<std::uintptr_t>(q2) % 1024 << std::endl;
auto q3 = mkl_realloc(q2, 3000);
std::cout << reinterpret_cast<std::uintptr_t>(q3) % 1024 << std::endl;

Вывод на моем компьютере:

0
784
784
0
0
0
...