Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmalloc.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qmalloc.h"
6#include "qplatformdefs.h"
7
8#include <stdlib.h>
9#include <string.h>
10
11/*
12 Define the container allocation functions in a separate file, so that our
13 users can easily override them.
14*/
15
17
18void *qMallocAligned(size_t size, size_t alignment)
19{
20 return qReallocAligned(nullptr, size, 0, alignment);
21}
22
23void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment)
24{
25 // fake an aligned allocation
26 void *actualptr = oldptr ? static_cast<void **>(oldptr)[-1] : nullptr;
27 if (alignment <= sizeof(void *)) {
28 // special, fast case
29 void **newptr = static_cast<void **>(realloc(actualptr, newsize + sizeof(void *)));
30 if (!newptr)
31 return nullptr;
32 if (newptr == actualptr) {
33 // realloc succeeded without reallocating
34 return oldptr;
35 }
36
37 *newptr = newptr;
38 return newptr + 1;
39 }
40
41 // malloc returns pointers aligned at least at sizeof(size_t) boundaries
42 // but usually more (8- or 16-byte boundaries).
43 // So we overallocate by alignment-sizeof(size_t) bytes, so we're guaranteed to find a
44 // somewhere within the first alignment-sizeof(size_t) that is properly aligned.
45
46 // However, we need to store the actual pointer, so we need to allocate actually size +
47 // alignment anyway.
48
49 qptrdiff oldoffset = oldptr ? static_cast<char *>(oldptr) - static_cast<char *>(actualptr) : 0;
50 void *real = realloc(actualptr, newsize + alignment);
51 if (!real)
52 return nullptr;
53
54 quintptr faked = reinterpret_cast<quintptr>(real) + alignment;
55 faked &= ~(alignment - 1);
56 void **faked_ptr = reinterpret_cast<void **>(faked);
57
58 if (oldptr) {
59 qptrdiff newoffset = reinterpret_cast<char *>(faked_ptr) - static_cast<char *>(real);
60 if (oldoffset != newoffset)
61 memmove(faked_ptr, static_cast<char *>(real) + oldoffset, qMin(oldsize, newsize));
62 }
63
64 // now save the value of the real pointer at faked-sizeof(void*)
65 // by construction, alignment > sizeof(void*) and is a power of 2, so
66 // faked-sizeof(void*) is properly aligned for a pointer
67 faked_ptr[-1] = real;
68
69 return faked_ptr;
70}
71
72void qFreeAligned(void *ptr)
73{
74 if (!ptr)
75 return;
76 void **ptr2 = static_cast<void **>(ptr);
77 free(ptr2[-1]);
78}
79
80QT_END_NAMESPACE
void * qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment)
Definition qmalloc.cpp:23
void qFreeAligned(void *ptr)
Definition qmalloc.cpp:72
QT_BEGIN_NAMESPACE void * qMallocAligned(size_t size, size_t alignment)
Definition qmalloc.cpp:18