NXC: strncpy for identity src=dest ?
Posted: 27 Feb 2011, 14:36
I couldn't find it in the docs:
will strncpy safely work for identity src=dest?
strncpy(str,str,10);
will strncpy safely work for identity src=dest?
strncpy(str,str,10);
Give a child a robot, he'll play for an hour. Teach him to build, and he'll play forever.
https://mindboards.org:443/
Code: Select all
string str, str2;
str2 = str.substr (3,12);doc-helmut wrote:I couldn't find it in the docs:
will strncpy safely work for identity src=dest?
strncpy(str,str,10);
I don't understand why you need to ask the community this question. It is trivially easy to see for yourself whether this works or not. Based on the way that strsubset is implemented in the firmware source code it would appear that it is not safe to use the same variable as both the source and the destination since it reallocates space for the destination array before it uses memmove to copy data from the source to the desination. Since it has already reallocated the destination array which happens to also be the source array it has clobbered the original data.doc-helmut wrote:I couldn't find it in the docs:
will strncpy safely work for identity src=dest?
strncpy(str,str,10);
Code: Select all
though, since the resulting string will automatically be null terminated in NXC while it will not be automatically null terminated in C.Code: Select all
NXT_STATUS cCmdDSArrayAlloc(DS_ELEMENT_ID DSElementID, UWORD Offset, UWORD NewCount)
{
NXT_STATUS Status = NO_ERR;
UWORD DVIndex;
UWORD OldCount;
UWORD i;
#if VMProfilingCode
ULONG enterTime= dTimerReadHiRes();
#endif
NXT_ASSERT(cCmdIsDSElementIDSane(DSElementID));
//Only arrays are valid here
//!!! Recommended to upgrade NXT_ASSERT to ERR_INSTR return
NXT_ASSERT(cCmdDSType(DSElementID) == TC_ARRAY);
DVIndex = cCmdGetDVIndex(DSElementID, Offset);
OldCount = DV_ARRAY[DVIndex].Count;
if(OldCount == NewCount)
goto allocExit;
Status = cCmdDVArrayAlloc(DVIndex, NewCount);
if (Status < NO_ERR)
goto allocExit;
if(!IS_AGGREGATE_TYPE(cCmdDSType(INC_ID(DSElementID))))
goto allocExit;
if (OldCount > NewCount)
{
//Free dope vectors for sub-arrays.
for (i = NewCount; i < OldCount; i++)
{
Status = cCmdFreeSubArrayDopeVectors(INC_ID(DSElementID), ARRAY_ELEM_OFFSET(DVIndex, i));
if (IS_ERR(Status))
goto allocExit;
}
}
else if (OldCount < NewCount)
{
//Alloc dope vectors for sub-arrays. Set up DVIndexes
for (i = OldCount; i < NewCount; i++)
{
Status = cCmdAllocSubArrayDopeVectors(INC_ID(DSElementID), ARRAY_ELEM_OFFSET(DVIndex, i));
if (IS_ERR(Status))
goto allocExit;
}
}
NXT_ASSERT(cCmdVerifyMemMgr());
allocExit:
#if VMProfilingCode
memMgrTime += dTimerReadHiRes() - enterTime;
#endif
return Status;
}
NXT_STATUS cCmdDVArrayAlloc(DV_INDEX DVIndex, UWORD NewCount)
{
NXT_STATUS Status = NO_ERR;
UBYTE *pData;
UWORD ArraySize, InplaceSize;
UWORD NextDVIndex;
UWORD OldCount;
OldCount = DV_ARRAY[DVIndex].Count;
if (OldCount == NewCount)
{
//Nothing to alloc. Return.
return Status;
}
else if (OldCount > NewCount)
{
//Already have the space. Shrink inplace.
DV_ARRAY[DVIndex].Count = NewCount;
return Status;
}
else // need to grow array
{
//Calculate new array size
ArraySize = NewCount * DV_ARRAY[DVIndex].ElemSize;
//Try growing inplace
// If the Offset == NOT_AN_OFFSET then the array has never been allocated and can't grow inplace.
if (DV_ARRAY[DVIndex].Offset != NOT_AN_OFFSET)
{
//Get pointer to next dope vector in dataspace
if (DV_ARRAY[DVIndex].Link != NOT_A_DS_ID)
{
NextDVIndex = DV_ARRAY[DVIndex].Link;
InplaceSize = DV_ARRAY[NextDVIndex].Offset - DV_ARRAY[DVIndex].Offset;
}
else
{
//Last element in dataspace.
NXT_ASSERT(DVIndex == VarsCmd.MemMgr.Tail);
InplaceSize = VarsCmd.DataspaceSize - DV_ARRAY[DVIndex].Offset;
}
if (ArraySize <= InplaceSize)
{
DV_ARRAY[DVIndex].Count = NewCount;
return Status;
}
}
//Can't grow inplace, have to allocate new space
//Make sure we properly align for type
//!!! This could also overflow memory (make PoolSize > POOL_MAX_SIZE) if we're within 3 bytes of the end.
// I don't think it matters because if it does happend, we'll trigger the ERR_MEM below and compact.
// During compaction, we'll reclaim these unused bytes.
//!!! Aligning beginning of ALL arrays to 4 byte address
ALIGN_TO_MOD(VarsCmd.PoolSize, SIZE_ULONG);
ALIGN_TO_MOD(VarsCmd.DataspaceSize, SIZE_ULONG);
if (VarsCmd.PoolSize + ArraySize >= POOL_MAX_SIZE)
{
//Not enough memory available
return ERR_MEM;
}
//Get data from end of pool
pData = VarsCmd.Pool + VarsCmd.PoolSize;
//Grow pool and dataspace
VarsCmd.PoolSize += ArraySize;
VarsCmd.DataspaceSize += ArraySize;
//Move old Array Data to new allocation
if(OldCount)
memmove(pData, VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset, (UWORD)(DV_ARRAY[DVIndex].ElemSize * OldCount));
//!!! Clear mem so old mem doesn't contain stale data. Not strictly needed.
#if WIN_DEBUG || defined(ARM_DEBUG)
memset(VarsCmd.pDataspace + DV_ARRAY[DVIndex].Offset, 0xFF, (UWORD)(DV_ARRAY[DVIndex].ElemSize * OldCount));
#endif
//Update dope vector
DV_ARRAY[DVIndex].Offset = pData - VarsCmd.pDataspace;
DV_ARRAY[DVIndex].Count = NewCount;
//Move dope vector to end of MemMgr list
Status = cCmdMemMgrMoveToTail(DVIndex);
if (IS_ERR(Status))
return Status;
NXT_ASSERT(cCmdVerifyMemMgr());
}
return Status;
}
Code: Select all
asm { strsubset src, src, 8, 2 }