Created
March 29, 2025 15:58
-
-
Save zachreizner/ea0f24ff0fc5c9b3206f4fa406cff437 to your computer and use it in GitHub Desktop.
CnC Generals AsciiString
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void AsciiString::ensureUniqueBufferOfSize(int numCharsNeeded, Bool preserveData, const char* strToCopy, const char* strToCat) | |
{ | |
validate(); | |
if (m_data && | |
m_data->m_refCount == 1 && | |
m_data->m_numCharsAllocated >= numCharsNeeded) | |
{ | |
// no buffer manhandling is needed (it's already large enough, and unique to us) | |
if (strToCopy) | |
strcpy(m_data->peek(), strToCopy); | |
if (strToCat) | |
strcat(m_data->peek(), strToCat); | |
return; | |
} | |
int minBytes = sizeof(AsciiStringData) + numCharsNeeded*sizeof(char); | |
if (minBytes > MAX_LEN) | |
throw ERROR_OUT_OF_MEMORY; | |
int actualBytes = TheDynamicMemoryAllocator->getActualAllocationSize(minBytes); | |
AsciiStringData* newData = (AsciiStringData*)TheDynamicMemoryAllocator->allocateBytesDoNotZero(actualBytes, "STR_AsciiString::ensureUniqueBufferOfSize"); | |
newData->m_refCount = 1; | |
newData->m_numCharsAllocated = (actualBytes - sizeof(AsciiStringData))/sizeof(char); | |
#if defined(_DEBUG) || defined(_INTERNAL) | |
newData->m_debugptr = newData->peek(); // just makes it easier to read in the debugger | |
#endif | |
if (m_data && preserveData) | |
strcpy(newData->peek(), m_data->peek()); | |
else | |
newData->peek()[0] = 0; | |
// do these BEFORE releasing the old buffer, so that self-copies | |
// or self-cats will work correctly. | |
if (strToCopy) | |
strcpy(newData->peek(), strToCopy); | |
if (strToCat) | |
strcat(newData->peek(), strToCat); | |
releaseBuffer(); | |
m_data = newData; | |
validate(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class AsciiString | |
{ | |
private: | |
// Note, this is a Plain Old Data Structure... don't | |
// add a ctor/dtor, 'cuz they won't ever be called. | |
struct AsciiStringData | |
{ | |
#if defined(_DEBUG) || defined(_INTERNAL) | |
const char* m_debugptr; // just makes it easier to read in the debugger | |
#endif | |
unsigned short m_refCount; // reference count | |
unsigned short m_numCharsAllocated; // length of data allocated | |
// unsigned int m_padding; | |
// char m_stringdata[]; | |
inline char* peek() { return (char*)(this+1); } | |
}; | |
#ifdef _DEBUG | |
void validate() const; | |
#else | |
inline void validate() const { } | |
#endif | |
protected: | |
AsciiStringData* m_data; // pointer to ref counted string data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Breakpoint 1, AsciiString::ensureUniqueBufferOfSize (this=0x7fffffffd080, numCharsNeeded=5, preserveData=false, strToCopy=0x555555dc6691 "None", strToCat=0x0) at /data/scratch/CnC/Generals/Code/GameEngine/Source/Common/System/AsciiString.cpp:126 | |
126 validate(); | |
(gdb) n | |
128 if (m_data && | |
(gdb) | |
140 int minBytes = sizeof(AsciiStringData) + numCharsNeeded*sizeof(char); | |
(gdb) p minBytes | |
$1 = 0 | |
(gdb) n | |
141 if (minBytes > MAX_LEN) | |
(gdb) p minBytes | |
$2 = 21 | |
(gdb) n | |
144 int actualBytes = TheDynamicMemoryAllocator->getActualAllocationSize(minBytes); | |
(gdb) | |
145 AsciiStringData* newData = (AsciiStringData*)TheDynamicMemoryAllocator->allocateBytesDoNotZero(actualBytes, "STR_AsciiString::ensureUniqueBufferOfSize"); | |
(gdb) p actualBytes | |
$3 = 32 | |
(gdb) n | |
146 newData->m_refCount = 1; | |
(gdb) p newData | |
$4 = (AsciiString::AsciiStringData *) 0x7ffff6e92370 | |
(gdb) n | |
147 newData->m_numCharsAllocated = (actualBytes - sizeof(AsciiStringData))/sizeof(char); | |
(gdb) p newData | |
$5 = (AsciiString::AsciiStringData *) 0x7ffff6e92370 | |
(gdb) p *newData | |
$6 = {m_debugptr = 0x0, m_refCount = 1, m_numCharsAllocated = 0} | |
(gdb) n | |
149 newData->m_debugptr = newData->peek(); // just makes it easier to read in the debugger | |
(gdb) p *newData | |
$7 = {m_debugptr = 0x0, m_refCount = 1, m_numCharsAllocated = 16} | |
(gdb) n | |
152 if (m_data && preserveData) | |
(gdb) p *newData | |
$8 = {m_debugptr = 0x7ffff6e92374 "\377\177", m_refCount = 1, m_numCharsAllocated = 16} | |
(gdb) n | |
155 newData->peek()[0] = 0; | |
(gdb) p *newData | |
$9 = {m_debugptr = 0x7ffff6e92374 "\377\177", m_refCount = 1, m_numCharsAllocated = 16} | |
(gdb) n | |
159 if (strToCopy) | |
(gdb) p *newData | |
$10 = {m_debugptr = 0x7f00f6e92374 <error: Cannot access memory at address 0x7f00f6e92374>, m_refCount = 1, m_numCharsAllocated = 16} | |
(gdb) p newData | |
$11 = (AsciiString::AsciiStringData *) 0x7ffff6e92370 | |
(gdb) p newData->peek() | |
$12 = 0x7ffff6e92374 "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
m_debugptr
is initially0x7ffff6e92374
and then suddenly becomes0x7f00f6e92374
afternewData->peek()[0] = 0;
.