Страница 1 из 2
LoadStringW, неизвестный размер
Добавлено: 30 ноя 2010, 12:34
Apokal
Добрый день всем, подскажите незнающему как рещить проблемку.
Для правильной работы функции LoadStringW нужно в качестве одного из параметров указать разер буфера, в которой будет записана строка. Но как быть если пользователь предоставляет только указатель на будущий буфер? Тобишь мне самому нужно как то выяснить размер строки которая загрузится и выделить память на которую будет ссылатся переданый мне указатель... Как бы это сделать?
Re: LoadStringW, неизвестный размер
Добавлено: 30 ноя 2010, 13:04
Decoder
Тогда тебе должны передавать не только указатель на массив, но и его длину.
Либо эта величина должна быть предопределена в виде константы, например так:
#define MAX_BUFF_LEN 512
В этом случае пользователь должен будет использовать эту константу для создания массива и
ты её сможешь использовать в качестве параметра для LoadString.
В качестве альтернативы можно передавать не указатель на массив символов, а ссылку на класс типа CString.
Тогда ты сможешь просто вызывать метод CString::LoadString() без всяких дополнительных параметров.
Re: LoadStringW, неизвестный размер
Добавлено: 30 ноя 2010, 14:26
Apokal
Спасибо за ответ. Вариант с заранее определенным размером мне не подходит. Идея использовать CString интересна, но всетаки хотелось бы ограничится стандартным windows.h, но на крайняк можно и зделать так как Вы описали. Еще раз спасибо.
Re: LoadStringW, неизвестный размер
Добавлено: 30 ноя 2010, 17:08
Decoder
Если хочешь ограничиться функциями Windows API, то могу порекомендовать использовать функции GlobalAlloc() для выделения памяти и GlobalFree() для удаления. В саму функцию нужно передавать не указатель на массив, а переменную HGLOBAL. С помощью функции GlobalSize() можно будет узнать размер выделенной памяти. Чтобы обратиться к указателю на массив по переменной HGLOBAL, нужно использовать функции GlobalLock() и GlobalUnlock().
Re: LoadStringW, неизвестный размер
Добавлено: 01 дек 2010, 09:55
BBB
Из описания параметра nBufferMax в MSDN:
nBufferMax [in]
int
The size of the buffer, in characters. The string is truncated and null-terminated if it is longer than the number of characters specified. If this parameter is 0, then lpBuffer receives a read-only pointer to the resource itself.
Если вам хочется ТОЧНО выделить размер памяти, то, как я понял из описания, можно указать nBufferMax, в качестве lpBuffer передать свой указатель. После вызова функция заполнит его "read-only pointer"-ом. Далее с помощью lstrlen можно получить размер строки ресурса, выделить соответсвующее колиечство памяти (длина + 1) уже по "своему" указателю, и скопировать туда строку из полученного при вызове LoadString указателя.
Re: LoadStringW, неизвестный размер
Добавлено: 03 дек 2010, 16:52
Apokal
Спасибо еще раз всем за ответы. Пробовал использовать особенность параметра nBufferMax, но к сожалению в предоставленый мною указатель ничего не записывалось.
Я решил пойти немножко по-другому пути, но и тут возникла непонятная ошибка, прошу помочь.
Суть в том что вначале выделяю минимальный обьем памяти в который бы смог записать 10 WCHAR. Потом сравниваю количество записаных символов функцией LoadStringW в переменную size и размер буфера nBuffSize, если результат 1 или меньше значит буфер был мал для строки, поэтому освобождаю выделенную под него память, увеличию размер буфера и выделяю опять память, и так пока не будет достаточно места для строки.
Но происходит ошибка при вызове функции LocalFree() ( TestDll.exe -- прога в которой динамически гружу дллку, в которой находится функция с данным кодом)
Windows has triggered a breakpoint in TestDll.exe.
This may be due to a corruption of the heap, which indicates a bug in TestDll.exe or any of the DLLs it has loaded.
В следущем окне
Unhandled exception at 0x7765283b in TestDll.exe: 0xC0000374: Куча была повреждена.
Немогу понять в чем ошибка работы с кучей?
Код: Выделить всё
LPTSTR pszBuf = NULL;
size_t size = 0, nBuffSize = 10*sizeof(WCHAR);
pszBuf = (LPTSTR)LocalAlloc(LPTR,nBuffSize);
size=LoadStringW(GetModuleHandle(TEXT("RW7_Res.dll")),(uId+uLanguageId),pszBuf,nBuffSize);
if((nBuffSize-size)<=1)
do
{
LocalFree(pszBuf);
nBuffSize+=(10*sizeof(WCHAR));
pszBuf = (LPTSTR)LocalAlloc(LPTR,nBuffSize);
size=LoadStringW(GetModuleHandle(TEXT("RW7_Res.dll")),(uId+uLanguageId),pszBuf,nBuffSize);
} while((nBuffSize-size)<=1);
Re: LoadStringW, неизвестный размер
Добавлено: 06 дек 2010, 12:13
BBB
Пробовал использовать особенность параметра nBufferMax, но к сожалению в предоставленый мною указатель ничего не записывалось.
Рискну предположить, что что-то Вы не так поняли/делали. Т.к. скорее поверю в это, чем в то, что MSDN нагло врет
По ошибке.
Рискну предположить, что при присвоении значения переменной nBuffSize не нужно умножать на sizeof(WCHAR). Т.к. в ф-ию LoadStringW размер, по моему разумению, передается именно в WCHAR-ах! А Вы, по сути, передали размер в байтах. Т.е. LoadStringW, при такой подаче, в результате рассчитывает на буфер в два (sizeof(WCHAR)) раз бОльшего размера, чем ВЫ передали. Отсюда и развал хипа в конечном итоге.
Ну и немного "причесывания" кода. Зачем Вы сначала используете IF, а зтем while С ТЕМ ЖЕ САМЫМ условием?
Код: Выделить всё
if(<условие>)
do
{
.............
} while(<условие>);
Ведь то же самое можно записать как:
Re: LoadStringW, неизвестный размер
Добавлено: 25 янв 2011, 18:40
Hawk
А к чему цикл вообще ?
размер уже известен почему бы не сделать -
Код: Выделить всё
if( (size + 1) > (nBuffSize / sizeof(WCHAR)) )
{
LocalFree(pszBuf);
nBuffSize = (size + 1)*sizeof(WCHAR);
pszBuf = (LPTSTR)LocalAlloc(LPTR, nBuffSize );
size = LoadStringW(GetModuleHandle(TEXT("RW7_Res.dll")),(uId+uLanguageId),pszBuf, size);
pszBuf[size] = 0;
}
не уверен на 100% но думаю первый вызов можно без буфера сделать чтобы только размер получить -
size = LoadStringW(GetModuleHandle(TEXT("RW7_Res.dll")),(uId+uLanguageId), NULL, 0);
Кредитный рынок
Добавлено: 21 окт 2012, 22:38
sriditerrs
Курс доллара не стабилен
Добавлено: 21 окт 2012, 22:39
sriditerrs