LoadStringW, неизвестный размер
Модераторы: Duncon, Hawk, Romeo, Eugie
Добрый день всем, подскажите незнающему как рещить проблемку.
Для правильной работы функции LoadStringW нужно в качестве одного из параметров указать разер буфера, в которой будет записана строка. Но как быть если пользователь предоставляет только указатель на будущий буфер? Тобишь мне самому нужно как то выяснить размер строки которая загрузится и выделить память на которую будет ссылатся переданый мне указатель... Как бы это сделать?
Для правильной работы функции LoadStringW нужно в качестве одного из параметров указать разер буфера, в которой будет записана строка. Но как быть если пользователь предоставляет только указатель на будущий буфер? Тобишь мне самому нужно как то выяснить размер строки которая загрузится и выделить память на которую будет ссылатся переданый мне указатель... Как бы это сделать?
For Those Who About The Rock We Salute You!!!
Тогда тебе должны передавать не только указатель на массив, но и его длину.
Либо эта величина должна быть предопределена в виде константы, например так:
#define MAX_BUFF_LEN 512
В этом случае пользователь должен будет использовать эту константу для создания массива и
ты её сможешь использовать в качестве параметра для LoadString.
В качестве альтернативы можно передавать не указатель на массив символов, а ссылку на класс типа CString.
Тогда ты сможешь просто вызывать метод CString::LoadString() без всяких дополнительных параметров.
Либо эта величина должна быть предопределена в виде константы, например так:
#define MAX_BUFF_LEN 512
В этом случае пользователь должен будет использовать эту константу для создания массива и
ты её сможешь использовать в качестве параметра для LoadString.
В качестве альтернативы можно передавать не указатель на массив символов, а ссылку на класс типа CString.
Тогда ты сможешь просто вызывать метод CString::LoadString() без всяких дополнительных параметров.
Поумнеть несложно, куда труднее от дури избавиться.
Спасибо за ответ. Вариант с заранее определенным размером мне не подходит. Идея использовать CString интересна, но всетаки хотелось бы ограничится стандартным windows.h, но на крайняк можно и зделать так как Вы описали. Еще раз спасибо.
For Those Who About The Rock We Salute You!!!
Если хочешь ограничиться функциями Windows API, то могу порекомендовать использовать функции GlobalAlloc() для выделения памяти и GlobalFree() для удаления. В саму функцию нужно передавать не указатель на массив, а переменную HGLOBAL. С помощью функции GlobalSize() можно будет узнать размер выделенной памяти. Чтобы обратиться к указателю на массив по переменной HGLOBAL, нужно использовать функции GlobalLock() и GlobalUnlock().
Поумнеть несложно, куда труднее от дури избавиться.
Из описания параметра 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 указателя.
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 указателя.
Спасибо еще раз всем за ответы. Пробовал использовать особенность параметра 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: Куча была повреждена.
Немогу понять в чем ошибка работы с кучей?
Я решил пойти немножко по-другому пути, но и тут возникла непонятная ошибка, прошу помочь.
Суть в том что вначале выделяю минимальный обьем памяти в который бы смог записать 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);
For Those Who About The Rock We Salute You!!!
Рискну предположить, что что-то Вы не так поняли/делали. Т.к. скорее поверю в это, чем в то, что MSDN нагло вретПробовал использовать особенность параметра nBufferMax, но к сожалению в предоставленый мною указатель ничего не записывалось.

По ошибке.
Рискну предположить, что при присвоении значения переменной nBuffSize не нужно умножать на sizeof(WCHAR). Т.к. в ф-ию LoadStringW размер, по моему разумению, передается именно в WCHAR-ах! А Вы, по сути, передали размер в байтах. Т.е. LoadStringW, при такой подаче, в результате рассчитывает на буфер в два (sizeof(WCHAR)) раз бОльшего размера, чем ВЫ передали. Отсюда и развал хипа в конечном итоге.
Ну и немного "причесывания" кода. Зачем Вы сначала используете IF, а зтем while С ТЕМ ЖЕ САМЫМ условием?

Код: Выделить всё
if(<условие>)
do
{
.............
} while(<условие>);
Код: Выделить всё
do while(<условие>)
{
.............
};
А к чему цикл вообще ?
размер уже известен почему бы не сделать -
не уверен на 100% но думаю первый вызов можно без буфера сделать чтобы только размер получить -
size = LoadStringW(GetModuleHandle(TEXT("RW7_Res.dll")),(uId+uLanguageId), NULL, 0);
размер уже известен почему бы не сделать -
Код: Выделить всё
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;
}
size = LoadStringW(GetModuleHandle(TEXT("RW7_Res.dll")),(uId+uLanguageId), NULL, 0);
-
- Сообщения: 22
- Зарегистрирован: 21 окт 2012, 22:31
- Откуда: Россия
- Контактная информация:
Об этом и об востановление экономики , доллар растёт и об Австралийский доллар под давлением
на http://rus-crediter.ru/
На нашем сайте всегда интересные новости.
на http://rus-crediter.ru/
На нашем сайте всегда интересные новости.
-
- Сообщения: 22
- Зарегистрирован: 21 окт 2012, 22:31
- Откуда: Россия
- Контактная информация:
Об этих новостях и об обзор кредитного рынка , Банк Англии планирует повышение процентной ставки и об Австралийский доллар под давлением
на http://rus-crediter.ru/
На нашем портале всегда свежие новости.
на http://rus-crediter.ru/
На нашем портале всегда свежие новости.