Возврат wchar_t* в из метода dll
От: akamda1989  
Дата: 27.03.12 13:16
Оценка:
Имеется функция в ddl, возвращающая строку wchar_t*. При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'. И спонтанно возникает экзепшн с кодом c0000005. В чем я могу быть не прав, подскажи плз!
Re: Возврат wchar_t* в из метода dll
От: pugv Россия  
Дата: 27.03.12 13:27
Оценка:
A>При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'.
Причин может быть куча.
При ведите хотя бы сигнатуру функции, а лучше кусок кода.
Re[2]: Возврат wchar_t* в из метода dll
От: akamda1989  
Дата: 27.03.12 13:36
Оценка: +1
Здравствуйте, pugv, Вы писали:

A>>При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'.

P>Причин может быть куча.
P>При ведите хотя бы сигнатуру функции, а лучше кусок кода.

Я подумал, что наверное лучше будет не возвращать wchat_t, а передавать в качестве параметра. Так или нет?
Re: Возврат wchar_t* в из метода dll
От: uzhas Ниоткуда  
Дата: 27.03.12 13:46
Оценка:
Здравствуйте, akamda1989, Вы писали:

A>Имеется функция в ddl, возвращающая строку wchar_t*. При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'. И спонтанно возникает экзепшн с кодом c0000005. В чем я могу быть не прав, подскажи плз!

предположу, что вы не следите за временем жизни тех данных, которые лежать под wchar_t*
вам нужно на клиентской стороне выделить буфер, передать указатель на него в длл, код в длл заполнит буфер нужными данными
далее вы можете работать с этими данными

возможен другой сценарий:
вы обращаетесь к ддл, она внутри выделяет нужный буфер, заполняет его данными, затем возвращает вам wchar_t* указатель на жти данные, при этом буфер все еще жив
далее клиент что-то делает с данными
в конце клиент говорит этой длл, что данный буфер уже не нужен и длл его прибивает
Re[3]: Возврат wchar_t* в из метода dll
От: pugv Россия  
Дата: 27.03.12 13:50
Оценка:
A>Я подумал, что наверное лучше будет не возвращать wchat_t, а передавать в качестве параметра. Так или нет?
Да это не важно. Это всего лишь указатель. Если Вы заранее не знаете длину строки, выделить буфер до вызова будет достаточно проблематично.
А если хотите, чтобы Вам помогли найти ошибку, приведите код. Где и как выделяется память под строку?
Re[2]: Возврат wchar_t* в из метода dll
От: akamda1989  
Дата: 27.03.12 13:53
Оценка:
Здравствуйте, uzhas, Вы писали:

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


A>>Имеется функция в ddl, возвращающая строку wchar_t*. При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'. И спонтанно возникает экзепшн с кодом c0000005. В чем я могу быть не прав, подскажи плз!

U>предположу, что вы не следите за временем жизни тех данных, которые лежать под wchar_t*
U>вам нужно на клиентской стороне выделить буфер, передать указатель на него в длл, код в длл заполнит буфер нужными данными
U>далее вы можете работать с этими данными

U>возможен другой сценарий:

U>вы обращаетесь к ддл, она внутри выделяет нужный буфер, заполняет его данными, затем возвращает вам wchar_t* указатель на жти данные, при этом буфер все еще жив
U>далее клиент что-то делает с данными
U>в конце клиент говорит этой длл, что данный буфер уже не нужен и длл его прибивает

А можно передать в качестве параметра функции wchar_t*&? при этом передавать неинициализированный указатель, метод dll его инициализирует, а удаляем на клиентской стороне?
Re[3]: Возврат wchar_t* в из метода dll
От: pugv Россия  
Дата: 27.03.12 13:55
Оценка:
A>А можно передать в качестве параметра функции wchar_t*&? при этом передавать неинициализированный указатель, метод dll его инициализирует, а удаляем на клиентской стороне?
Можно Но я уже почти уверен в том, что Ваша проблема в том, как вы его инициализируете. Уж не используются ли случаем std::string.c_str(), std::string.data() без копирования?
Re[4]: Возврат wchar_t* в из метода dll
От: pugv Россия  
Дата: 27.03.12 14:00
Оценка:
P>Уж не используются ли случаем std::string.c_str(), std::string.data() без копирования?
Да, и std::string.copy() null-терминатор тоже сам не добавляет.
Re[5]: Возврат wchar_t* в из метода dll
От: akamda1989  
Дата: 28.03.12 05:14
Оценка:
Вот код, не понимаю в чем проблема... В случанйный момент возникает ошибка с кодом c0000005.

bool myClass::stop(wchar_t* &_xml)
{
        std::wstringstream ss;

        pugi::xml_document* rezDoc = new pugi::xml_document();

//создание xml с помощью pugi

        rezDoc->print(ss, "", pugi::format_raw, pugi::encoding_utf16_le);

        rezDoc->~xml_document();

        std::wstring s;

        const wchar_t* tmp = ss.str().c_str();

        _xml = new wchar_t[(wcslen(tmp) + 1) * sizeof(wchar_t)];
        wcscpy(_xml, tmp);
        _xml[(wcslen(tmp) + 1)] = L'\0';
}
//DLL:
myClass* sMs;

extern "C" __declspec(dllexport) bool stop(wchar_t* &_xml)
{
    try
    {
        sMs->stop(_xml);

        return true;
    }
    catch(char c)
    {
        return false;
    }
}

//клиентская сторона


            wchar_t* r = NULL;
            this->stop(r);

            double proximity = this->calculateProximity(QString::fromWCharArray(r));

            delete[] r;


Подскажите плз в чем не прав!
Re[6]: Возврат wchar_t* в из метода dll
От: icWasya  
Дата: 28.03.12 05:42
Оценка:
Здравствуйте, akamda1989, Вы писали:

A>Вот код, не понимаю в чем проблема... В случанйный момент возникает ошибка с кодом c0000005.


_xml[(wcslen(tmp) + 1)] = L'\0'; //<<==-- убрать +1

A>Подскажите плз в чем не прав!
Re[7]: Возврат wchar_t* в из метода dll
От: akamda1989  
Дата: 28.03.12 05:47
Оценка:
W> _xml[(wcslen(tmp) + 1)] = L'\0'; //<<==-- убрать +1

Согласен, но проблему ошибкой с кодом c0000005 не решило!
Re[6]: Возврат wchar_t* в из метода dll
От: DarkTranquillity  
Дата: 28.03.12 05:50
Оценка:
Здравствуйте, akamda1989, Вы писали:

A>Вот код, не понимаю в чем проблема... В случанйный момент возникает ошибка с кодом c0000005.


A>
A>bool myClass::stop(wchar_t* &_xml)
A>{
A>        std::wstringstream ss;

A>        pugi::xml_document* rezDoc = new pugi::xml_document();

A>//создание xml с помощью pugi

A>        rezDoc->print(ss, "", pugi::format_raw, pugi::encoding_utf16_le);

A>        rezDoc->~xml_document(); // Это что за извращение? Оператор delete мы не знаем? А если он перегружен для pugi::xml_document?

A>        std::wstring s;

A>        const wchar_t* tmp = ss.str().c_str(); // сразу после этой строчки в tmp будет неизвестно что
                                                        // ss.str() возвратит временный объект, у которого ты берешь указатель на данные, и который умрет сразу                       
                                                        // за точкой с запятой. Выводы?

A>        _xml = new wchar_t[(wcslen(tmp) + 1) * sizeof(wchar_t)];
A>        wcscpy(_xml, tmp);
A>        _xml[(wcslen(tmp) + 1)] = L'\0';
A>}
A>//DLL:
A>myClass* sMs; // где-то это инициализируется валидным объектом?

A>extern "C" __declspec(dllexport) bool stop(wchar_t* &_xml)
A>{
A>    try
A>    {
        sMs->>stop(_xml);

A>        return true;
A>    }
A>    catch(char c)
A>    {
A>        return false;
A>    }
A>}

A>//клиентская сторона


A>            wchar_t* r = NULL;
            this->>stop(r);

A>            double proximity = this->calculateProximity(QString::fromWCharArray(r));

A>            delete[] r;
A>


A>Подскажите плз в чем не прав!


Навскидку (сколько можно уже натыкаться на грабли с life time временного объекта?) — комментарии в коде.
Да, и может быть, shared_ptr спасет отца русской демократии?
Re[7]: Возврат wchar_t* в из метода dll
От: Аноним  
Дата: 28.03.12 06:15
Оценка:
DT>Навскидку (сколько можно уже натыкаться на грабли с life time временного объекта?) — комментарии в коде.
DT>Да, и может быть, shared_ptr спасет отца русской демократии?

Спасибо!
подскажите плз как граммотно написать?
const wchar_t* tmp = ss.str().c_str();[/b] // сразу после этой строчки в tmp будет неизвестно что
DT> // ss.str() возвратит временный объект, у которого ты берешь указатель на данные, и который умрет сразу
DT> // за точкой с запятой. Выводы?

A>> _xml = new wchar_t[(wcslen(tmp) + 1) * sizeof(wchar_t)];

A>> wcscpy(_xml, tmp);
A>> _xml[(wcslen(tmp) + 1)] = L'\0';

Можно так?


_xml = new wchar_t[ss.str().size() + 1) * sizeof(wchar_t)];
wcscpy(_xml, ss.str().c_str());
_xml[ss.str().size()] = L'\0';
Re[8]: Возврат wchar_t* в из метода dll
От: DarkTranquillity  
Дата: 28.03.12 08:41
Оценка:
Здравствуйте, Аноним, Вы писали:

DT>>Навскидку (сколько можно уже натыкаться на грабли с life time временного объекта?) — комментарии в коде.

DT>>Да, и может быть, shared_ptr спасет отца русской демократии?

А>Спасибо!

А> подскажите плз как граммотно написать?
А>const wchar_t* tmp = ss.str().c_str();[/b] // сразу после этой строчки в tmp будет неизвестно что
DT>> // ss.str() возвратит временный объект, у которого ты берешь указатель на данные, и который умрет сразу
DT>> // за точкой с запятой. Выводы?

A>>> _xml = new wchar_t[(wcslen(tmp) + 1) * sizeof(wchar_t)];

A>>> wcscpy(_xml, tmp);
A>>> _xml[(wcslen(tmp) + 1)] = L'\0';

А>Можно так?



А>
А>_xml = new wchar_t[ss.str().size() + 1) * sizeof(wchar_t)]; // Это что за фокусы??
А>wcscpy(_xml, ss.str().c_str());
А>_xml[ss.str().size()] = L'\0'; // Это зачем?
А>


Хосспади, молодой человек (я надеюсь, Вы молодой человек, и делаете курсовую), почитайте книгу про С++, что ли.
Что Вам неймется постоянно создавать временный объект из ss?
Так можно, но это же криво.

Хотя бы так:
const std::wstring &ref_str = ss.str();
_xml = new wchar_t[ref_str.size() + 1];
wcscpy(_xml, ref_str.c_str());
Re[8]: Возврат wchar_t* в из метода dll
От: Мишень-сан  
Дата: 28.03.12 10:23
Оценка:
Здравствуйте, akamda1989, Вы писали:

A>Согласен, но проблему ошибкой с кодом c0000005 не решило!


Управлять временем жизни объекта должен тот модуль, который его создал. Поэтому или shared_ptr, или функция для удаления в DLL
В win у каждого модуля ЕМНИП своя CRT-куча. Если выделять чанк в модуле, а уничтожать в клиентском коде — он будет создан в одной куче, а удалён в другой. Результат немного предсказуем.
Re[9]: Возврат wchar_t* в из метода dll
От: akamda1989  
Дата: 28.03.12 10:52
Оценка:
А почему не советуете использовать временный объект из ss?
Re[10]: Возврат wchar_t* в из метода dll
От: DarkTranquillity  
Дата: 28.03.12 11:10
Оценка:
Здравствуйте, akamda1989, Вы писали:

A>А почему не советуете использовать временный объект из ss?


Хотя бы потому, что код корявее и нечитабельнее, из-за возможного оверхеда, и опять же — чтобы не схватить случайно ту ситуацию, которая была у Вас — объект умирает раньше, чем заканчивают его использование.
Re[11]: Возврат wchar_t* в из метода dll
От: akamda1989  
Дата: 28.03.12 11:26
Оценка:
Здравствуйте, DarkTranquillity, Вы писали:

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


A>>А почему не советуете использовать временный объект из ss?


DT>Хотя бы потому, что код корявее и нечитабельнее, из-за возможного оверхеда, и опять же — чтобы не схватить случайно ту ситуацию, которая была у Вас — объект умирает раньше, чем заканчивают его использование.



Спасибо большое за консультацию!
Re[12]: Возврат wchar_t* в из метода dll
От: DarkTranquillity  
Дата: 28.03.12 12:01
Оценка:
Здравствуйте, akamda1989, Вы писали:

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


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


A>>>А почему не советуете использовать временный объект из ss?


DT>>Хотя бы потому, что код корявее и нечитабельнее, из-за возможного оверхеда, и опять же — чтобы не схватить случайно ту ситуацию, которая была у Вас — объект умирает раньше, чем заканчивают его использование.



A>Спасибо большое за консультацию!


Не за что, а вот литературку нужно почитать, и тренироваться, тренироваться...
Re[10]: Возврат wchar_t* в из метода dll
От: Мишень-сан  
Дата: 28.03.12 21:27
Оценка:
Здравствуйте, akamda1989, Вы писали:

A>А почему не советуете использовать временный объект из ss?


Потому что после выхода из функции, на стеке которой был выделен буфер, состояние покинутого стекового фрейма не определено. Это хак, может сработать, а может и нет.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.