Fixed linux listenserver startup problems
Fixed multiple buffer overruns and memory leaks.
This commit is contained in:
parent
c5031315bf
commit
74f1ab866b
29 changed files with 371 additions and 254 deletions
|
|
@ -1,93 +0,0 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
|
||||
// provide placment new to avoid stdc++ <new> header
|
||||
inline void *operator new (const size_t, void *ptr) noexcept {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// default allocator for cr-objects
|
||||
class Allocator : public Singleton <Allocator> {
|
||||
public:
|
||||
Allocator () = default;
|
||||
~Allocator () = default;
|
||||
|
||||
public:
|
||||
template <typename T> T *allocate (const size_t length = 1) {
|
||||
auto memory = reinterpret_cast <T *> (malloc (cr::max <size_t> (1u, length * sizeof (T))));
|
||||
|
||||
if (!memory) {
|
||||
plat.abort ();
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
template <typename T> void deallocate (T *memory) {
|
||||
free (memory);
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> void construct (T *memory, Args &&...args) {
|
||||
new (memory) T (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <typename T> void destruct (T *memory) {
|
||||
memory->~T ();
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> T *create (Args &&...args) {
|
||||
auto memory = allocate <T> ();
|
||||
new (memory) T (cr::forward <Args> (args)...);
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
template <typename T> T *createArray (const size_t amount) {
|
||||
auto memory = allocate <T> (amount);
|
||||
|
||||
for (size_t i = 0; i < amount; ++i) {
|
||||
new (memory + i) T ();
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
template <typename T> void destroy (T *memory) {
|
||||
if (memory) {
|
||||
destruct (memory);
|
||||
deallocate (memory);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (Allocator, alloc);
|
||||
|
||||
template <typename T> class UniquePtr;
|
||||
|
||||
// implment singleton with UniquePtr
|
||||
template <typename T> T &Singleton <T>::instance () {
|
||||
static const UniquePtr <T> instance_ { alloc.create <T> () };
|
||||
return *instance_;
|
||||
}
|
||||
|
||||
// declare destructor for pure-virtual classes
|
||||
#define CR_DECLARE_DESTRUCTOR() \
|
||||
void operator delete (void *ptr) { \
|
||||
alloc.deallocate (ptr); \
|
||||
} \
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-random.h>
|
||||
|
||||
|
|
@ -61,20 +61,20 @@ public:
|
|||
private:
|
||||
void destructElements () noexcept {
|
||||
for (size_t i = 0; i < length_; ++i) {
|
||||
alloc.destruct (&contents_[i]);
|
||||
Memory::destruct (&contents_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void transferElements (T *dest, T *src, size_t length) noexcept {
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
alloc.construct (&dest[i], cr::move (src[i]));
|
||||
alloc.destruct (&src[i]);
|
||||
Memory::construct (&dest[i], cr::move (src[i]));
|
||||
Memory::destruct (&src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy () {
|
||||
destructElements ();
|
||||
alloc.deallocate (contents_);
|
||||
Memory::release (contents_);
|
||||
}
|
||||
|
||||
void reset () {
|
||||
|
|
@ -83,7 +83,6 @@ private:
|
|||
length_ = 0;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
bool reserve (const size_t amount) {
|
||||
if (length_ + amount < capacity_) {
|
||||
|
|
@ -99,11 +98,11 @@ public:
|
|||
else {
|
||||
capacity = amount + capacity_ + 1;
|
||||
}
|
||||
auto data = alloc.allocate <T> (capacity);
|
||||
auto data = Memory::get <T> (capacity);
|
||||
|
||||
if (contents_) {
|
||||
transferElements (data, contents_, length_);
|
||||
alloc.deallocate (contents_);
|
||||
Memory::release (contents_);
|
||||
}
|
||||
|
||||
contents_ = data;
|
||||
|
|
@ -152,7 +151,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
}
|
||||
alloc.construct (&contents_[index], cr::forward <U> (object));
|
||||
Memory::construct (&contents_[index], cr::forward <U> (object));
|
||||
|
||||
if (index >= length_) {
|
||||
length_ = index + 1;
|
||||
|
|
@ -176,7 +175,7 @@ public:
|
|||
|
||||
if (index >= length_) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
alloc.construct (&contents_[i + index], cr::forward <U> (objects[i]));
|
||||
Memory::construct (&contents_[i + index], cr::forward <U> (objects[i]));
|
||||
}
|
||||
length_ = capacity;
|
||||
}
|
||||
|
|
@ -187,7 +186,7 @@ public:
|
|||
contents_[i + count - 1] = cr::move (contents_[i - 1]);
|
||||
}
|
||||
for (i = 0; i < count; ++i) {
|
||||
alloc.construct (&contents_[i + index], cr::forward <U> (objects[i]));
|
||||
Memory::construct (&contents_[i + index], cr::forward <U> (objects[i]));
|
||||
}
|
||||
length_ += count;
|
||||
}
|
||||
|
|
@ -206,7 +205,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
for (size_t i = index; i < index + count; ++i) {
|
||||
alloc.destruct (&contents_[i]);
|
||||
Memory::destruct (&contents_[i]);
|
||||
}
|
||||
length_ -= count;
|
||||
|
||||
|
|
@ -232,7 +231,7 @@ public:
|
|||
if (!reserve (1)) {
|
||||
return false;
|
||||
}
|
||||
alloc.construct (&contents_[length_], cr::forward <U> (object));
|
||||
Memory::construct (&contents_[length_], cr::forward <U> (object));
|
||||
++length_;
|
||||
|
||||
return true;
|
||||
|
|
@ -242,7 +241,7 @@ public:
|
|||
if (!reserve (1)) {
|
||||
return false;
|
||||
}
|
||||
alloc.construct (&contents_[length_], cr::forward <Args> (args)...);
|
||||
Memory::construct (&contents_[length_], cr::forward <Args> (args)...);
|
||||
++length_;
|
||||
|
||||
return true;
|
||||
|
|
@ -310,10 +309,10 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
auto data = alloc.allocate <T> (length_);
|
||||
auto data = Memory::get <T> (length_);
|
||||
transferElements (data, contents_, length_);
|
||||
|
||||
alloc.deallocate (contents_);
|
||||
Memory::release (contents_);
|
||||
|
||||
contents_ = data;
|
||||
capacity_ = length_;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,10 @@ protected:
|
|||
{ }
|
||||
|
||||
public:
|
||||
static T &instance (); // implemented in cr-alloc.h
|
||||
static T &instance () {
|
||||
static T __instance {};
|
||||
return __instance;
|
||||
}
|
||||
|
||||
public:
|
||||
T *operator -> () {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-array.h>
|
||||
#include <crlib/cr-deque.h>
|
||||
#include <crlib/cr-binheap.h>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-twin.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
|
@ -16,8 +15,8 @@ CR_NAMESPACE_BEGIN
|
|||
template <typename T> class Deque : private DenyCopying {
|
||||
private:
|
||||
size_t capacity_ {};
|
||||
T *contents_ {};
|
||||
|
||||
UniquePtr <T[]> contents_ {};
|
||||
Twin <size_t, size_t> index_ {};
|
||||
|
||||
private:
|
||||
|
|
@ -56,7 +55,7 @@ private:
|
|||
|
||||
void extendCapacity () {
|
||||
auto capacity = capacity_ ? capacity_ * 2 : 8;
|
||||
auto contents = cr::makeUnique <T[]> (sizeof (T) * capacity);
|
||||
auto contents = Memory::get <T> (sizeof (T) * capacity);
|
||||
|
||||
if (index_.first < index_.second) {
|
||||
for (size_t i = 0; i < index_.second - index_.first; ++i) {
|
||||
|
|
@ -76,14 +75,16 @@ private:
|
|||
index_.second = index_.second + (capacity_ - index_.first);
|
||||
index_.first = 0;
|
||||
}
|
||||
contents_ = cr::move (contents);
|
||||
Memory::release (contents_);
|
||||
|
||||
contents_ = contents;
|
||||
capacity_ = capacity;
|
||||
}
|
||||
|
||||
void destroy () {
|
||||
auto destruct = [&] (size_t start, size_t end) {
|
||||
for (size_t i = start; i < end; ++i) {
|
||||
alloc.destruct (&contents_[i]);
|
||||
Memory::destruct (&contents_[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -94,7 +95,7 @@ private:
|
|||
destruct (index_.first, capacity_);
|
||||
destruct (0, index_.second);
|
||||
}
|
||||
contents_ = nullptr;
|
||||
Memory::release (contents_);
|
||||
}
|
||||
|
||||
void reset () {
|
||||
|
|
@ -127,17 +128,17 @@ public:
|
|||
template <typename ...Args> void emplaceLast (Args &&...args) {
|
||||
auto rear = pickRearIndex ();
|
||||
|
||||
alloc.construct (&contents_[index_.second], cr::forward <Args> (args)...);
|
||||
Memory::construct (&contents_[index_.second], cr::forward <Args> (args)...);
|
||||
index_.second = rear;
|
||||
}
|
||||
|
||||
template <typename ...Args> void emplaceFront (Args &&...args) {
|
||||
index_.first = pickFrontIndex ();
|
||||
alloc.construct (&contents_[index_.first], cr::forward <Args> (args)...);
|
||||
Memory::construct (&contents_[index_.first], cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
void discardFront () {
|
||||
alloc.destruct (&contents_[index_.first]);
|
||||
Memory::destruct (&contents_[index_.first]);
|
||||
|
||||
if (index_.first == capacity_ - 1) {
|
||||
index_.first = 0;
|
||||
|
|
@ -154,7 +155,7 @@ public:
|
|||
else {
|
||||
index_.second--;
|
||||
}
|
||||
alloc.destruct (&contents_[index_.second]);
|
||||
Memory::destruct (&contents_[index_.second]);
|
||||
}
|
||||
|
||||
T popFront () {
|
||||
|
|
|
|||
|
|
@ -140,35 +140,10 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
Detour () = default;
|
||||
|
||||
Detour (StringRef module, StringRef name, T *address) {
|
||||
savedBytes_.resize (jmpBuffer_.length ());
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
(void) module;
|
||||
(void) name;
|
||||
|
||||
auto search = reinterpret_cast <uint8 *> (address);
|
||||
|
||||
while (*reinterpret_cast <uint16 *> (search) == 0x25ff) {
|
||||
search = **reinterpret_cast <uint8 ***> (search + 2);
|
||||
}
|
||||
|
||||
original_ = search;
|
||||
pageSize_ = static_cast <unsigned long> (sysconf (_SC_PAGE_SIZE));
|
||||
#else
|
||||
auto handle = GetModuleHandleA (module.chars ());
|
||||
|
||||
if (!handle) {
|
||||
original_ = reinterpret_cast <void *> (address);
|
||||
return;
|
||||
}
|
||||
original_ = reinterpret_cast <void *> (GetProcAddress (handle, name.chars ()));
|
||||
|
||||
if (!original_) {
|
||||
original_ = reinterpret_cast <void *> (address);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
initialize (module, name, address);
|
||||
}
|
||||
|
||||
~Detour () {
|
||||
|
|
@ -194,7 +169,37 @@ private:
|
|||
};
|
||||
|
||||
public:
|
||||
|
||||
void initialize (StringRef module, StringRef name, T *address) {
|
||||
savedBytes_.resize (jmpBuffer_.length ());
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
(void) module;
|
||||
(void) name;
|
||||
|
||||
auto ptr = reinterpret_cast <uint8 *> (address);
|
||||
|
||||
while (*reinterpret_cast <uint16 *> (ptr) == 0x25ff) {
|
||||
ptr = **reinterpret_cast <uint8 ***> (ptr + 2);
|
||||
}
|
||||
|
||||
original_ = ptr;
|
||||
pageSize_ = static_cast <unsigned long> (sysconf (_SC_PAGE_SIZE));
|
||||
#else
|
||||
auto handle = GetModuleHandleA (module.chars ());
|
||||
|
||||
if (!handle) {
|
||||
original_ = reinterpret_cast <void *> (address);
|
||||
return;
|
||||
}
|
||||
original_ = reinterpret_cast <void *> (GetProcAddress (handle, name.chars ()));
|
||||
|
||||
if (!original_) {
|
||||
original_ = reinterpret_cast <void *> (address);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void install (void *detour, const bool enable = false) {
|
||||
if (!original_) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -180,8 +180,8 @@ private:
|
|||
FreeFunction freeFun_ = nullptr;
|
||||
|
||||
public:
|
||||
inline MemFileStorage () = default;
|
||||
inline ~MemFileStorage () = default;
|
||||
explicit MemFileStorage () = default;
|
||||
~MemFileStorage () = default;
|
||||
|
||||
public:
|
||||
void initizalize (LoadFunction loader, FreeFunction unloader) {
|
||||
|
|
@ -212,14 +212,14 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
*size = static_cast <int> (file.length ());
|
||||
auto data = alloc.allocate <uint8> (*size);
|
||||
auto data = Memory::get <uint8> (*size);
|
||||
|
||||
file.read (data, *size);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void defaultUnload (void *buffer) {
|
||||
alloc.deallocate (buffer);
|
||||
Memory::release (buffer);
|
||||
}
|
||||
|
||||
static String loadToString (StringRef filename) {
|
||||
|
|
|
|||
|
|
@ -36,11 +36,13 @@ template <> struct Hash <const char *> {
|
|||
|
||||
template <> struct Hash <int32> {
|
||||
uint32 operator () (int32 key) const noexcept {
|
||||
key = ((key >> 16) ^ key) * 0x119de1f3;
|
||||
key = ((key >> 16) ^ key) * 0x119de1f3;
|
||||
key = (key >> 16) ^ key;
|
||||
auto result = static_cast <uint32> (key);
|
||||
|
||||
return key;
|
||||
result = ((result >> 16) ^ result) * 0x119de1f3;
|
||||
result = ((result >> 16) ^ result) * 0x119de1f3;
|
||||
result = (result >> 16) ^ result;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
|
@ -31,9 +31,6 @@ private:
|
|||
|
||||
virtual R invoke (Args &&...) = 0;
|
||||
virtual UniquePtr <LambdaFunctorWrapper> clone () const = 0;
|
||||
|
||||
public:
|
||||
CR_DECLARE_DESTRUCTOR ();
|
||||
};
|
||||
|
||||
template <typename T> class LambdaFunctor : public LambdaFunctorWrapper {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public:
|
|||
|
||||
private:
|
||||
Handle handle_ = nullptr;
|
||||
bool unloadable_ = true;
|
||||
|
||||
public:
|
||||
explicit SharedLibrary () = default;
|
||||
|
|
@ -43,22 +44,28 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
bool load (StringRef file) noexcept {
|
||||
bool load (StringRef file, bool unloadable = true) noexcept {
|
||||
if (*this) {
|
||||
unload ();
|
||||
}
|
||||
unloadable_ = unloadable;
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
handle_ = LoadLibraryA (file.chars ());
|
||||
#elif defined (CR_OSX)
|
||||
handle_ = dlopen (file.chars (), RTLD_NOW | RTLD_LOCAL);
|
||||
#else
|
||||
handle_ = dlopen (file.chars (), RTLD_NOW | RTLD_DEEPBIND | RTLD_LOCAL);
|
||||
auto loadFlags = RTLD_NOW | RTLD_LOCAL;
|
||||
|
||||
#if defined (CR_LINUX) && !defined (__SANITIZE_ADDRESS__)
|
||||
loadFlags |= RTLD_DEEPBIND;
|
||||
#endif
|
||||
handle_ = dlopen (file.chars (), loadFlags);
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
bool locate (Handle address) {
|
||||
unloadable_ = false;
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
|
|
@ -75,16 +82,17 @@ public:
|
|||
plat.bzero (&dli, sizeof (dli));
|
||||
|
||||
if (dladdr (address, &dli)) {
|
||||
return load (dli.dli_fname);
|
||||
return load (dli.dli_fname, false);
|
||||
}
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
void unload () noexcept {
|
||||
if (!*this) {
|
||||
if (!handle_ || !unloadable_) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
FreeLibrary (static_cast <HMODULE> (handle_));
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ private:
|
|||
PrintFunction printFun_;
|
||||
|
||||
public:
|
||||
SimpleLogger () = default;
|
||||
explicit SimpleLogger () = default;
|
||||
~SimpleLogger () = default;
|
||||
|
||||
public:
|
||||
|
|
|
|||
52
ext/crlib/cr-memory.h
Normal file
52
ext/crlib/cr-memory.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
|
||||
// provide placment new to avoid stdc++ <new> header
|
||||
inline void *operator new (const size_t, void *ptr) noexcept {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// internal memory manager
|
||||
class Memory final {
|
||||
public:
|
||||
Memory () = default;
|
||||
~Memory () = default;
|
||||
|
||||
public:
|
||||
template <typename T> static T *get (const size_t length = 1) {
|
||||
auto memory = reinterpret_cast <T *> (malloc (cr::max <size_t> (1u, length * sizeof (T))));
|
||||
|
||||
if (!memory) {
|
||||
plat.abort ();
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
template <typename T> static void release (T *memory) {
|
||||
free (memory);
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> static void construct (T *memory, Args &&...args) {
|
||||
new (memory) T (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <typename T> static void destruct (T *memory) {
|
||||
memory->~T ();
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
39
ext/crlib/cr-override.h
Normal file
39
ext/crlib/cr-override.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Project <yapb@jeefo.net>.
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
|
||||
void *operator new (size_t size) noexcept {
|
||||
return cr::Memory::get <void *> (size);
|
||||
}
|
||||
|
||||
void *operator new [] (size_t size) noexcept {
|
||||
return cr::Memory::get <void *> (size);
|
||||
}
|
||||
|
||||
void operator delete (void *ptr) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
void operator delete [] (void *ptr) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
void operator delete (void *ptr, size_t) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
void operator delete [] (void *ptr, size_t) noexcept {
|
||||
cr::Memory::release (ptr);
|
||||
}
|
||||
|
||||
CR_LINKAGE_C void __cxa_pure_virtual () {
|
||||
cr::plat.abort ("pure virtual function call");
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ private:
|
|||
uint64 state_ { static_cast <uint64> (time (nullptr)) };
|
||||
|
||||
public:
|
||||
Random () = default;
|
||||
explicit Random () = default;
|
||||
~Random () = default;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
#include <crlib/cr-array.h>
|
||||
|
|
@ -420,7 +420,13 @@ public:
|
|||
length = calcLength (str, length);
|
||||
|
||||
resize (length);
|
||||
memcpy (&chars_[0], str, length);
|
||||
|
||||
if (str) {
|
||||
memcpy (&chars_[0], str, length);
|
||||
}
|
||||
else {
|
||||
chars_[0] = kNullChar;
|
||||
}
|
||||
|
||||
length_ = length;
|
||||
chars_[length_] = kNullChar;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-memory.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
|
@ -53,7 +53,7 @@ public:
|
|||
|
||||
private:
|
||||
void destroy () {
|
||||
alloc.destroy (ptr_);
|
||||
delete ptr_;
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ public:
|
|||
|
||||
private:
|
||||
void destroy () {
|
||||
alloc.destroy (ptr_);
|
||||
delete[] ptr_;
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -156,6 +156,7 @@ public:
|
|||
T &operator [] (size_t index) {
|
||||
return ptr_[index];
|
||||
}
|
||||
|
||||
const T &operator [] (size_t index) const {
|
||||
return ptr_[index];
|
||||
}
|
||||
|
|
@ -192,11 +193,12 @@ namespace detail {
|
|||
}
|
||||
|
||||
template <typename T, typename... Args> typename detail::UniqueIf <T>::SingleObject makeUnique (Args &&... args) {
|
||||
return UniquePtr <T> (alloc.create <T> (cr::forward <Args> (args)...));
|
||||
return UniquePtr <T> (new T (cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
template <typename T> typename detail::UniqueIf <T>::UnknownBound makeUnique (size_t size) {
|
||||
return UniquePtr <T> (alloc.createArray <typename detail::ClearExtent <T>::Type> (size));
|
||||
using Type = typename detail::ClearExtent <T>::Type;
|
||||
return UniquePtr<T> (new Type[size] ());
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> typename detail::UniqueIf <T>::KnownBound makeUnique (Args &&...) = delete;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue