Правильный способ обнуления объекта AnsiString
Как обнулить объект AnsiString? Например:
void TesteClass::test()
{
AnsiString cardNumber = "1234567890123456";
..
}
Объект AnsiString уничтожается автоматически, но его внутренние данные не очищаются, поэтому средство считывания памяти может считывать информацию. Нам нужно обнулить эти данные, чтобы конфиденциальная информация не попала в память.
Класс AnsiString имеет метод c_str()
для прямого доступа к внутренним данным, но делать что-то подобное не рекомендуется:
memset(cardNumber.c_str(), 0, cardNumber.Length());
Как правильно обнулить внутренние данные AnsiString до уничтожения объекта?
1 ответ
Там нет ничего плохого в использовании memset()
как вы показали. С помощью c_str()
таким образом, является правильным (до тех пор, пока вы не превышаете Length()
, поскольку c_str()
возвращает указатель на постоянную память, если AnsiString
пусто):
void TesteClass::test()
{
AnsiString cardNumber = "1234567890123456";
// ...
memset(cardNumber.c_str(), 0, cardNumber.Length());
}
Поскольку вас беспокоит утечка информации, рассмотрите возможность использования SecureZeroMemory()
вместо memset()
(см. в чем смысл SecureZeroMemory?).
Чтобы автоматизировать обнуление (так что вам не нужно это делать), подумайте об упаковке AnsiString
в стиле RAII class
/ struct
(вы не можете извлечь из AnsiString
напрямую, RTL не позволяет), чей деструктор выполняет обнуление, а затем использует это class
/ struct
где необходимо вместо использования AnsiString
непосредственно.
Просто будь осторожен, так как AnsiString
использует данные с подсчетом ссылок, поэтому не обнуляйте данные, если ваш AnsiString
это единственный экземпляр, ссылающийся на данные:
class SaferAnsiString
{
private:
AnsiString m_Str;
void CheckZeroNeeded()
{
// AnsiString gained a public RefCount() method in C++Builder 2009.
// In earlier versions, access the reference count manually...
#ifdef _DELPHI_STRING_UNICODE
if (m_Str.RefCount() == 1)
#else
const void *data = m_Str.data();
if ((data) && (static_cast<const int*>(data)[-2] == 1))
#endif
SecureZeroMemory(m_Str.c_str(), m_Str.Length());
}
public:
SaferAnsiString(const AnsiString &src = AnsiString())
: m_Str(src)
{
}
~SaferAnsiString()
{
CheckZeroNeeded();
}
SaferAnsiString& operator=(const AnsiString &rhs)
{
CheckZeroNeeded();
m_Str = rhs;
return *this;
}
operator AnsiString () const { return m_Str; }
// other methods as needed...
};
void TesteClass::test()
{
SaferAnsiString cardNumber = "1234567890123456";
// ...
}