Имеется функция в ddl, возвращающая строку wchar_t*. При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'. И спонтанно возникает экзепшн с кодом c0000005. В чем я могу быть не прав, подскажи плз!
A>При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'.
Причин может быть куча.
При ведите хотя бы сигнатуру функции, а лучше кусок кода.
Здравствуйте, pugv, Вы писали:
A>>При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'. P>Причин может быть куча. P>При ведите хотя бы сигнатуру функции, а лучше кусок кода.
Я подумал, что наверное лучше будет не возвращать wchat_t, а передавать в качестве параметра. Так или нет?
Здравствуйте, akamda1989, Вы писали:
A>Имеется функция в ddl, возвращающая строку wchar_t*. При тестировании этой функции не в dll, а в исходниках — работает все нормально. При работе же с dll куда-то периодически пропадает кончный терминал L'\0'. И спонтанно возникает экзепшн с кодом c0000005. В чем я могу быть не прав, подскажи плз!
предположу, что вы не следите за временем жизни тех данных, которые лежать под wchar_t*
вам нужно на клиентской стороне выделить буфер, передать указатель на него в длл, код в длл заполнит буфер нужными данными
далее вы можете работать с этими данными
возможен другой сценарий:
вы обращаетесь к ддл, она внутри выделяет нужный буфер, заполняет его данными, затем возвращает вам wchar_t* указатель на жти данные, при этом буфер все еще жив
далее клиент что-то делает с данными
в конце клиент говорит этой длл, что данный буфер уже не нужен и длл его прибивает
A>Я подумал, что наверное лучше будет не возвращать wchat_t, а передавать в качестве параметра. Так или нет?
Да это не важно. Это всего лишь указатель. Если Вы заранее не знаете длину строки, выделить буфер до вызова будет достаточно проблематично.
А если хотите, чтобы Вам помогли найти ошибку, приведите код. Где и как выделяется память под строку?
Здравствуйте, 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 его инициализирует, а удаляем на клиентской стороне?
A>А можно передать в качестве параметра функции wchar_t*&? при этом передавать неинициализированный указатель, метод dll его инициализирует, а удаляем на клиентской стороне?
Можно Но я уже почти уверен в том, что Ваша проблема в том, как вы его инициализируете. Уж не используются ли случаем std::string.c_str(), std::string.data() без копирования?
P>Уж не используются ли случаем std::string.c_str(), std::string.data() без копирования?
Да, и std::string.copy() null-терминатор тоже сам не добавляет.
Здравствуйте, 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';
Здравствуйте, Аноним, Вы писали:
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?
Так можно, но это же криво.
Здравствуйте, akamda1989, Вы писали:
A>Согласен, но проблему ошибкой с кодом c0000005 не решило!
Управлять временем жизни объекта должен тот модуль, который его создал. Поэтому или shared_ptr, или функция для удаления в DLL
В win у каждого модуля ЕМНИП своя CRT-куча. Если выделять чанк в модуле, а уничтожать в клиентском коде — он будет создан в одной куче, а удалён в другой. Результат немного предсказуем.
Здравствуйте, akamda1989, Вы писали:
A>А почему не советуете использовать временный объект из ss?
Хотя бы потому, что код корявее и нечитабельнее, из-за возможного оверхеда, и опять же — чтобы не схватить случайно ту ситуацию, которая была у Вас — объект умирает раньше, чем заканчивают его использование.
Здравствуйте, DarkTranquillity, Вы писали:
DT>Здравствуйте, akamda1989, Вы писали:
A>>А почему не советуете использовать временный объект из ss?
DT>Хотя бы потому, что код корявее и нечитабельнее, из-за возможного оверхеда, и опять же — чтобы не схватить случайно ту ситуацию, которая была у Вас — объект умирает раньше, чем заканчивают его использование.
Здравствуйте, akamda1989, Вы писали:
A>Здравствуйте, DarkTranquillity, Вы писали:
DT>>Здравствуйте, akamda1989, Вы писали:
A>>>А почему не советуете использовать временный объект из ss?
DT>>Хотя бы потому, что код корявее и нечитабельнее, из-за возможного оверхеда, и опять же — чтобы не схватить случайно ту ситуацию, которая была у Вас — объект умирает раньше, чем заканчивают его использование.
A>Спасибо большое за консультацию!
Не за что, а вот литературку нужно почитать, и тренироваться, тренироваться...
Здравствуйте, akamda1989, Вы писали:
A>А почему не советуете использовать временный объект из ss?
Потому что после выхода из функции, на стеке которой был выделен буфер, состояние покинутого стекового фрейма не определено. Это хак, может сработать, а может и нет.