尝试清理一些代码,我想知道以下是否是将uint16_t强制转换为wchar_t的安全方法。
#if ! defined(MARKUP_SIZEOFWCHAR)
#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000
#define MARKUP_SIZEOFWCHAR 4
#else
#define MARKUP_SIZEOFWCHAR 2
#endif
void FileReader::parseBuffer(char * buffer, int length)
{
//start by looking for a vrsn
//Header seek around for a vrns followed by 32 bit size descriptor
//read 32 bits at a time
int cursor = 0;
char vrsn[5] = "vrsn";
cursor = this->searchForMarker(cursor, length, vrsn, buffer);
int32_t size = this->getObjectSizeForMarker(cursor, length, buffer);
cursor = cursor + 7; //advance cursor past marker and size
wchar_t *version = this->getObjectForSizeAndCursor(size, cursor, buffer);
wcout << version;
delete[] version; //this pointer is dest from getObjectForSizeAndCursor
}
-
wchar_t* FileReader::getObjectForSizeAndCursor(int32_t size, int cursor, char *buffer) {
int wlen = size/2;
uint32_t *dest = new uint32_t[wlen+1];
unsigned char *ptr = (unsigned char *)(buffer + cursor);
for(int i=0; i<wlen; i++) {
#if MARKUP_SIZEOFWCHAR == 4 // sizeof(wchar_t) == 4
char padding[2] = {'\0','\0'};
dest[i] = (padding[0] << 24) + (padding[1] << 16) + (ptr[0] << 8) + ptr[1];
#else // sizeof(wchar_t) == 2
dest[i] = (ptr[0] << 8) + ptr[1];
#endif
ptr += 2;
cout << ptr;
}
return (wchar_t *)dest;
}
我对使用填充的方式有任何范围问题吗?我会在调用函数中delete dest[]
时泄漏填充吗?
答案 0 :(得分:0)
区别
#if MARKUP_SIZEOFWCHAR == 4 // sizeof(wchar_t) == 4
char padding[2] = {'\0','\0'};
dest[i] = (padding[0] << 24) + (padding[1] << 16) + (ptr[0] << 8) + ptr[1];
#else // sizeof(wchar_t) == 2
dest[i] = (ptr[0] << 8) + ptr[1];
#endif
完全没必要。 <{1}}为0,因此向左移动将其保持为0,添加它无效。
编译器可能会或可能不会在每次循环迭代中优化双字节数组padding[i]
的分配,但由于它是一个自动数组,因此它不会以任何方式泄漏。
由于循环中使用的类型是无符号的,只需使用
padding
非常安全。 (字节顺序当然必须正确。)
有关
dest[i] = (ptr[0] << 8) + ptr[1];
您应该让return (wchar_t *)dest;
的类型取决于dest
的大小,如果wchar_t
(和uint16_t*
),则应为sizeof(wchar_t) == 2
。
答案 1 :(得分:0)
你想做的事情是行不通的。它在几个方面被打破了,但让我们专注于演员。
您的问题与您的代码不符。您的代码使用uint32_t
,而您的问题则询问uint16_t
。但这没关系,因为既不会起作用。
如果您需要使用wchar_t
,那么您实际应该使用 wchar_t
。如果你的目标是取char*
的两个连续字节并将它们复制到wchar_t
的前两个字节,那么就这样做。
这是一个更好的代码版本,实际上工作(在某种程度上从char*
复制两个字节并假装它是{{} 1}}):
wchar_t
另外,由于我们正在使用std::wstring FileReader::getObjectForSizeAndCursor(int32_t size, int cursor, char *buffer) {
int wlen = size/2;
std::wstring out(wlen);
unsigned char *ptr = (unsigned char *)(buffer + cursor);
for(int i=0; i<wlen; i++) {
out[i] = (ptr[0] << 8) + ptr[1];
ptr += 2;
cout << ptr;
}
return out;
}
之类的正确RAII类,因此没有内存泄漏的可能性。