Максимальная длина данных BSTR
От: degtyarenko_d  
Дата: 26.06.09 12:40
Оценка:
Здравствуйте! Столкнулся с проблемой такого характера:
есть библиотека, которая транслирует данные в приложение на VB6, вообщем все бы хорошо, но в момент
передачи в одной из функций указателя на char* большого блока данных экземпляру COM класса bstr_t, являющегося обверткой для BSTR, программа попросту зависает, никаких exceptions, error, ничего! Пробовал сделать с помощью ф-ии SysAllocStringLen(char* A2W(src), UINT len) такая же фигня. Так вот не ужели максимальная длина данных типа BSTR sizeof(UINT) ~ 4 bytes то есть 65535 символов и нужно переделывать все по другому?
Re: Максимальная длина данных BSTR
От: ioni Россия  
Дата: 26.06.09 13:11
Оценка:
Здравствуйте, degtyarenko_d, Вы писали:

_> Здравствуйте! Столкнулся с проблемой такого характера:

_>есть библиотека, которая транслирует данные в приложение на VB6, вообщем все бы хорошо, но в момент
_>передачи в одной из функций указателя на char* большого блока данных экземпляру COM класса bstr_t, являющегося обверткой для BSTR, программа попросту зависает, никаких exceptions, error, ничего! Пробовал сделать с помощью ф-ии SysAllocStringLen(char* A2W(src), UINT len) такая же фигня. Так вот не ужели максимальная длина данных типа BSTR sizeof(UINT) ~ 4 bytes то есть 65535 символов и нужно переделывать все по другому?

Вполне возможно, ведь в этой строке скрытые первые пару байт указывают на длину строки
Re[2]: Максимальная длина данных BSTR
От: angry.andrew Украина  
Дата: 26.06.09 13:46
Оценка: +1
Здравствуйте, ioni, Вы писали:

I>Здравствуйте, degtyarenko_d, Вы писали:


_>> Здравствуйте! Столкнулся с проблемой такого характера:

_>>есть библиотека, которая транслирует данные в приложение на VB6, вообщем все бы хорошо, но в момент
_>>передачи в одной из функций указателя на char* большого блока данных экземпляру COM класса bstr_t, являющегося обверткой для BSTR, программа попросту зависает, никаких exceptions, error, ничего! Пробовал сделать с помощью ф-ии SysAllocStringLen(char* A2W(src), UINT len) такая же фигня. Так вот не ужели максимальная длина данных типа BSTR sizeof(UINT) ~ 4 bytes то есть 65535 символов и нужно переделывать все по другому?

I>Вполне возможно, ведь в этой строке скрытые первые пару байт указывают на длину строки


Что-то вы, ребята, путаете. Длина BSTR хранится в четырех байтах, а не паре. А 4 байта — это 2^32, а не 65535.
Насколько мне известно, длина BSTR ограничена только объемом свободной памяти.
Re[3]: Максимальная длина данных BSTR
От: Vi2 Удмуртия http://www.adem.ru
Дата: 29.06.09 04:43
Оценка: 2 (1)
Здравствуйте, angry.andrew, Вы писали:

AA>Что-то вы, ребята, путаете. Длина BSTR хранится в четырех байтах, а не паре. А 4 байта — это 2^32, а не 65535.

AA>Насколько мне известно, длина BSTR ограничена только объемом свободной памяти.

От себя добавлю, что есть исходник макроса A2W и такой материал BUG in _com_util::ConvertStringToBSTR and _com_util::ConvertBSTRToString (оттуда цитата:

Now we can see what is going on inside that function.

1. Get length of char string.
2. Allocate memory on the stack using alloca() function. This is the place where it fails if char string is too long for the stack. And MS coders do not care if there is not enough memory on the stack. And finally why use stack here at all?
3. String is converted using MultiByteToWideChar()
4. If conversion failed, raise COM exception.
5. And now SysAllocString() is called.

), говорящие о том, что используются функции выделения строк в стеке. Поэтому большие размеры строк недопустимы.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Максимальная длина данных BSTR
От: kubic2009  
Дата: 03.07.09 01:46
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>Здравствуйте, angry.andrew, Вы писали:


AA>>Что-то вы, ребята, путаете. Длина BSTR хранится в четырех байтах, а не паре. А 4 байта — это 2^32, а не 65535.

AA>>Насколько мне известно, длина BSTR ограничена только объемом свободной памяти.

Vi2>От себя добавлю, что есть исходник макроса A2W и такой материал BUG in _com_util::ConvertStringToBSTR and _com_util::ConvertBSTRToString (оттуда цитата:

....
Vi2>), говорящие о том, что используются функции выделения строк в стеке. Поэтому большие размеры строк недопустимы.
В этом макросе используется преобразование строки через стэк, т.е. это ограничение только макроса A2W.
Re[3]: Максимальная длина данных BSTR
От: kubic2009  
Дата: 03.07.09 01:57
Оценка:
Здравствуйте, angry.andrew, Вы писали:

AA>Здравствуйте, ioni, Вы писали:


I>>Здравствуйте, degtyarenko_d, Вы писали:


_>>> Здравствуйте! Столкнулся с проблемой такого характера:

_>>>есть библиотека, которая транслирует данные в приложение на VB6, вообщем все бы хорошо, но в момент
_>>>передачи в одной из функций указателя на char* большого блока данных экземпляру COM класса bstr_t, являющегося обверткой для BSTR, программа попросту зависает, никаких exceptions, error, ничего! Пробовал сделать с помощью ф-ии SysAllocStringLen(char* A2W(src), UINT len) такая же фигня. Так вот не ужели максимальная длина данных типа BSTR sizeof(UINT) ~ 4 bytes то есть 65535 символов и нужно переделывать все по другому?

I>>Вполне возможно, ведь в этой строке скрытые первые пару байт указывают на длину строки


AA>Что-то вы, ребята, путаете. Длина BSTR хранится в четырех байтах, а не паре. А 4 байта — это 2^32, а не 65535.

AA>Насколько мне известно, длина BSTR ограничена только объемом свободной памяти.
Длина BSTR ограничена типом данных второго параметра WInAPI функции SysAllocStringLen unsigned int, если 32бита, то максамально 4294967295, если 64-бита, то максамально 18446744073709551615
Re[4]: Максимальная длина данных BSTR
От: degtyarenko_d  
Дата: 03.07.09 11:37
Оценка:
Здравствуйте, kubic2009, Вы писали:

K>Здравствуйте, angry.andrew, Вы писали:


AA>>Здравствуйте, ioni, Вы писали:


I>>>Здравствуйте, degtyarenko_d, Вы писали:


_>>>> Здравствуйте! Столкнулся с проблемой такого характера:

_>>>>есть библиотека, которая транслирует данные в приложение на VB6, вообщем все бы хорошо, но в момент
_>>>>передачи в одной из функций указателя на char* большого блока данных экземпляру COM класса bstr_t, являющегося обверткой для BSTR, программа попросту зависает, никаких exceptions, error, ничего! Пробовал сделать с помощью ф-ии SysAllocStringLen(char* A2W(src), UINT len) такая же фигня. Так вот не ужели максимальная длина данных типа BSTR sizeof(UINT) ~ 4 bytes то есть 65535 символов и нужно переделывать все по другому?

I>>>Вполне возможно, ведь в этой строке скрытые первые пару байт указывают на длину строки


AA>>Что-то вы, ребята, путаете. Длина BSTR хранится в четырех байтах, а не паре. А 4 байта — это 2^32, а не 65535.

AA>>Насколько мне известно, длина BSTR ограничена только объемом свободной памяти.
K>Длина BSTR ограничена типом данных второго параметра WInAPI функции SysAllocStringLen unsigned int, если 32бита, то максамально 4294967295, если 64-бита, то максамально 18446744073709551615

Друзья, спасибо за приведенные ответы, но все же каким образом, не влезая в кухню со стеком, запихнуть огромный char* в BSTR (если 32бита, то максамально 4294967295, чего вполне достаточно)?
Re[5]: Максимальная длина данных BSTR
От: Fwiffo Россия  
Дата: 03.07.09 11:45
Оценка:
Здравствуйте, degtyarenko_d, Вы писали:

_>Друзья, спасибо за приведенные ответы, но все же каким образом, не влезая в кухню со стеком, запихнуть огромный char* в BSTR (если 32бита, то максамально 4294967295, чего вполне достаточно)?


Насколько я понял, просто не пользоваться макросом A2W и _bstr_t. У самой SysAllocStringLen таких ограничений нет.
Re[6]: Максимальная длина данных BSTR
От: degtyarenko_d  
Дата: 03.07.09 13:30
Оценка:
Вообщем нарыл вот такую функцию без использования ограничивающих макросов, но проблема не пропала, при дебаге попадаю в блок
if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())

#define BUG_ARR_MAX 2000000
inline BSTR ConvStringToBSTR(const char* pSrc)
{
    if(!pSrc) return NULL;
    
    DWORD cwch;
    
    BSTR wsOut(NULL);
    
    if(cwch = ::MultiByteToWideChar(CP_ACP, 0, pSrc, 
        -1, NULL, 0))//get size minus NULL terminator
        
    {
        cwch--;
        wsOut = ::SysAllocStringLen(NULL, cwch);
        
        if(wsOut)
        {
            if(!::MultiByteToWideChar(CP_ACP, 
                0, pSrc, -1, wsOut, cwch))
            {
                if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
                    return wsOut;
                ::SysFreeString(wsOut);//must clean up
                
                wsOut = NULL;
            }
        }
        
    };
    
    return wsOut;
};

int main(int argc, char* argv[])
{
    char *szBuf = new char[BUG_ARR_MAX];
    
    BSTR bst = _com_util_fix::ConvertStringToBSTR(szBuf);
}


Есть у кого-то какие-то идеи?
Re[5]: Максимальная длина данных BSTR
От: degtyarenko_d  
Дата: 03.07.09 13:38
Оценка:
Здравствуйте, kubic2009, Вы писали:

K>Здравствуйте, Vi2, Вы писали:


Vi2>>Здравствуйте, angry.andrew, Вы писали:


AA>>>Что-то вы, ребята, путаете. Длина BSTR хранится в четырех байтах, а не паре. А 4 байта — это 2^32, а не 65535.

AA>>>Насколько мне известно, длина BSTR ограничена только объемом свободной памяти.

Vi2>>От себя добавлю, что есть исходник макроса A2W и такой материал BUG in _com_util::ConvertStringToBSTR and _com_util::ConvertBSTRToString (оттуда цитата:

K>....
Vi2>>), говорящие о том, что используются функции выделения строк в стеке. Поэтому большие размеры строк недопустимы.
K>В этом макросе используется преобразование строки через стэк, т.е. это ограничение только макроса A2W.

Хм, и как же обойти этот макрос A2W(), раз он критичен для больших размеров?
Re[7]: Максимальная длина данных BSTR
От: Fwiffo Россия  
Дата: 03.07.09 15:50
Оценка: 1 (1)
Здравствуйте, degtyarenko_d, Вы писали:

_>Вообщем нарыл вот такую функцию без использования ограничивающих макросов, но проблема не пропала, при дебаге попадаю в блок

_>if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())

_>[ccode]

_>#define BUG_ARR_MAX 2000000
_>inline BSTR ConvStringToBSTR(const char* pSrc)
_>{
_> if(!pSrc) return NULL;

_> DWORD cwch;


_> BSTR wsOut(NULL);


_> if(cwch = ::MultiByteToWideChar(CP_ACP, 0, pSrc,

_> -1, NULL, 0))//get size minus NULL terminator

_> {

_> cwch--;
_> wsOut = ::SysAllocStringLen(NULL, cwch);

_> if(wsOut)

_> {
_> if(!::MultiByteToWideChar(CP_ACP,
_> 0, pSrc, -1, wsOut, cwch))
_> {
_> if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
_> return wsOut;
_> ::SysFreeString(wsOut);//must clean up

_> wsOut = NULL;

_> }
_> }

_> };


_> return wsOut;

_>};

_>Есть у кого-то какие-то идеи?


Есть. Выкинуть это и написать самому, полезнее будет
Первый вызов MultiByteToWideChar возвращает необходимый размер буфера, неудивительно что буфера размером на символ меньше ей не хватает.
Re[8]: Максимальная длина данных BSTR
От: degtyarenko_d  
Дата: 08.07.09 10:15
Оценка:
Здравствуйте, Fwiffo, Вы писали:

F>Здравствуйте, degtyarenko_d, Вы писали:


_>>Вообщем нарыл вот такую функцию без использования ограничивающих макросов, но проблема не пропала, при дебаге попадаю в блок

_>>if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())

_>>[ccode]

_>>#define BUG_ARR_MAX 2000000
_>>inline BSTR ConvStringToBSTR(const char* pSrc)
_>>{
_>> if(!pSrc) return NULL;

_>> DWORD cwch;


_>> BSTR wsOut(NULL);


_>> if(cwch = ::MultiByteToWideChar(CP_ACP, 0, pSrc,

_>> -1, NULL, 0))//get size minus NULL terminator

_>> {

_>> cwch--;
_>> wsOut = ::SysAllocStringLen(NULL, cwch);

_>> if(wsOut)

_>> {
_>> if(!::MultiByteToWideChar(CP_ACP,
_>> 0, pSrc, -1, wsOut, cwch))
_>> {
_>> if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
_>> return wsOut;
_>> ::SysFreeString(wsOut);//must clean up

_>> wsOut = NULL;

_>> }
_>> }

_>> };


_>> return wsOut;

_>>};

_>>Есть у кого-то какие-то идеи?


F>Есть. Выкинуть это и написать самому, полезнее будет

F>Первый вызов MultiByteToWideChar возвращает необходимый размер буфера, неудивительно что буфера размером на символ меньше ей не хватает.


Спасибо огромное, Fwiffo!!! Сделал размер +1 и все заработало!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.