Skip to content

Commit 2a15286

Browse files
authored
Merge pull request #1053 from bruvzg/fix_release_memalloc
Fix incorrect memory allocation in release builds.
2 parents 2f07eb0 + ba4b501 commit 2a15286

File tree

4 files changed

+72
-21
lines changed

4 files changed

+72
-21
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ jobs:
1818
matrix:
1919
include:
2020
- name: 🐧 Linux (GCC)
21-
os: ubuntu-18.04
21+
os: ubuntu-20.04
2222
platform: linux
2323
artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
2424
artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a
2525
cache-name: linux-x86_64
2626

2727
- name: 🐧 Linux (GCC, Double Precision)
28-
os: ubuntu-18.04
28+
os: ubuntu-20.04
2929
platform: linux
3030
artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
3131
artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
@@ -56,7 +56,7 @@ jobs:
5656
cache-name: macos-universal
5757

5858
- name: 🤖 Android (arm64)
59-
os: ubuntu-18.04
59+
os: ubuntu-20.04
6060
platform: android
6161
artifact-name: godot-cpp-android-arm64-release
6262
artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
@@ -133,7 +133,7 @@ jobs:
133133

134134
linux-cmake:
135135
name: 🐧 Build (Linux, GCC, CMake)
136-
runs-on: ubuntu-18.04
136+
runs-on: ubuntu-20.04
137137
steps:
138138
- name: Checkout
139139
uses: actions/checkout@v3
@@ -157,7 +157,7 @@ jobs:
157157
158158
linux-cmake-ninja:
159159
name: 🐧 Build (Linux, GCC, CMake Ninja)
160-
runs-on: ubuntu-18.04
160+
runs-on: ubuntu-20.04
161161
steps:
162162
- name: Checkout
163163
uses: actions/checkout@v3

include/godot_cpp/core/memory.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040

4141
#include <type_traits>
4242

43+
#ifndef PAD_ALIGN
44+
#define PAD_ALIGN 16 //must always be greater than this at much
45+
#endif
46+
4347
void *operator new(size_t p_size, const char *p_description); ///< operator new that takes a description and uses MemoryStaticPool
4448
void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)); ///< operator new that takes a description and uses MemoryStaticPool
4549
void *operator new(size_t p_size, void *p_pointer, size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
@@ -64,9 +68,9 @@ class Memory {
6468
Memory();
6569

6670
public:
67-
static void *alloc_static(size_t p_bytes);
68-
static void *realloc_static(void *p_memory, size_t p_bytes);
69-
static void free_static(void *p_ptr);
71+
static void *alloc_static(size_t p_bytes, bool p_pad_align = false);
72+
static void *realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align = false);
73+
static void free_static(void *p_ptr, bool p_pad_align = false);
7074
};
7175

7276
_ALWAYS_INLINE_ void postinitialize_handler(void *) {}
@@ -140,7 +144,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") {
140144
same strategy used by std::vector, and the Vector class, so it should be safe.*/
141145

142146
size_t len = sizeof(T) * p_elements;
143-
uint64_t *mem = (uint64_t *)Memory::alloc_static(len);
147+
uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true);
144148
T *failptr = nullptr; // Get rid of a warning.
145149
ERR_FAIL_COND_V(!mem, failptr);
146150
*(mem - 1) = p_elements;
@@ -169,7 +173,7 @@ void memdelete_arr(T *p_class) {
169173
}
170174
}
171175

172-
Memory::free_static(ptr);
176+
Memory::free_static(ptr, true);
173177
}
174178

175179
struct _GlobalNil {

include/godot_cpp/templates/cowdata.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ void CowData<T>::_unref(void *p_data) {
217217
}
218218

219219
// free mem
220-
Memory::free_static((uint8_t *)p_data);
220+
Memory::free_static((uint8_t *)p_data, true);
221221
}
222222

223223
template <class T>
@@ -233,7 +233,7 @@ uint32_t CowData<T>::_copy_on_write() {
233233
/* in use by more than me */
234234
uint32_t current_size = *_get_size();
235235

236-
uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size));
236+
uint32_t *mem_new = (uint32_t *)Memory::alloc_static(_get_alloc_size(current_size), true);
237237

238238
new (mem_new - 2) SafeNumeric<uint32_t>(1); // refcount
239239
*(mem_new - 1) = current_size; // size
@@ -286,15 +286,15 @@ Error CowData<T>::resize(int p_size) {
286286
if (alloc_size != current_alloc_size) {
287287
if (current_size == 0) {
288288
// alloc from scratch
289-
uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size);
289+
uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true);
290290
ERR_FAIL_COND_V(!ptr, ERR_OUT_OF_MEMORY);
291291
*(ptr - 1) = 0; // size, currently none
292292
new (ptr - 2) SafeNumeric<uint32_t>(1); // refcount
293293

294294
_ptr = (T *)ptr;
295295

296296
} else {
297-
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size);
297+
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
298298
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
299299
new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount
300300

@@ -324,7 +324,7 @@ Error CowData<T>::resize(int p_size) {
324324
}
325325

326326
if (alloc_size != current_alloc_size) {
327-
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size);
327+
uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true);
328328
ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY);
329329
new (_ptrnew - 2) SafeNumeric<uint32_t>(rc); // refcount
330330

src/core/memory.cpp

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,63 @@
3434

3535
namespace godot {
3636

37-
void *Memory::alloc_static(size_t p_bytes) {
38-
return internal::gde_interface->mem_alloc(p_bytes);
37+
void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
38+
#ifdef DEBUG_ENABLED
39+
bool prepad = false; // Alredy pre paded in the engine.
40+
#else
41+
bool prepad = p_pad_align;
42+
#endif
43+
44+
void *mem = internal::gde_interface->mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0));
45+
ERR_FAIL_COND_V(!mem, nullptr);
46+
47+
if (prepad) {
48+
uint8_t *s8 = (uint8_t *)mem;
49+
return s8 + PAD_ALIGN;
50+
} else {
51+
return mem;
52+
}
3953
}
4054

41-
void *Memory::realloc_static(void *p_memory, size_t p_bytes) {
42-
return internal::gde_interface->mem_realloc(p_memory, p_bytes);
55+
void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
56+
if (p_memory == nullptr) {
57+
return alloc_static(p_bytes, p_pad_align);
58+
} else if (p_bytes == 0) {
59+
free_static(p_memory, p_pad_align);
60+
return nullptr;
61+
}
62+
63+
uint8_t *mem = (uint8_t *)p_memory;
64+
65+
#ifdef DEBUG_ENABLED
66+
bool prepad = false; // Alredy pre paded in the engine.
67+
#else
68+
bool prepad = p_pad_align;
69+
#endif
70+
71+
if (prepad) {
72+
mem -= PAD_ALIGN;
73+
mem = (uint8_t *)internal::gde_interface->mem_realloc(mem, p_bytes + PAD_ALIGN);
74+
ERR_FAIL_COND_V(!mem, nullptr);
75+
return mem + PAD_ALIGN;
76+
} else {
77+
return (uint8_t *)internal::gde_interface->mem_realloc(mem, p_bytes);
78+
}
4379
}
4480

45-
void Memory::free_static(void *p_ptr) {
46-
internal::gde_interface->mem_free(p_ptr);
81+
void Memory::free_static(void *p_ptr, bool p_pad_align) {
82+
uint8_t *mem = (uint8_t *)p_ptr;
83+
84+
#ifdef DEBUG_ENABLED
85+
bool prepad = false; // Alredy pre paded in the engine.
86+
#else
87+
bool prepad = p_pad_align;
88+
#endif
89+
90+
if (prepad) {
91+
mem -= PAD_ALIGN;
92+
}
93+
internal::gde_interface->mem_free(mem);
4794
}
4895

4996
_GlobalNil::_GlobalNil() {

0 commit comments

Comments
 (0)