Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы с STL vector, исключение в STL 
V
    Опции темы
mantissa
Дата 23.11.2007, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



Привет Великий ALL!
Может кто сталкивался с подобным и поможет разобраться в следующем....
имеем:
  код проги Win32 на С++,
  Visual MS .net 2003
  STL ее же поставки
использую контейнер vector<string> (например v)
 вар.1. 
   после чистки v.clear()  вызываю функцию и передаю в ней ссылку на v
   на 2 вызове после 3 или 4 вставки v.push_back вызывает исключение и программа слетает
   если всего 2 вставки, то проблем не заметил...
вар.2.
  выношу чистку в ту функцию (ставлю перед циклом)
  проблема пропадает... все работает

НУ КАКАЯ ЕМУ (контейнеру) РАЗНИЦА????
с ув. BSD
PM MAIL   Вверх
Sartorius
Дата 23.11.2007, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 1
Всего: 37



 код в студию.
PM MAIL ICQ   Вверх
NiJazz
Дата 23.11.2007, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


Профиль
Группа: Экс. модератор
Сообщений: 2286
Регистрация: 10.8.2003
Где: Москва

Репутация: 2
Всего: 23



Следующее работало в VS 2k5 SP1:
Код

#include <string>
#include <vector>

void f( std::vector<std::string>& v )
{
    v.push_back( "1" );
    v.push_back( "2" );
    v.push_back( "3" );
    v.push_back( "4" );
}

int _tmain(int argc, _TCHAR* argv[])
{    
    std::vector<std::string> v;

    v.push_back( "1" );
    v.push_back( "2" );
    v.push_back( "3" );

    v.clear();

    f( v );

    return 0;
}


Добавлено через 1 минуту и 33 секунды
Попробуй выставить блок catch ( const std::exception& ex ) и посмотри, что вернёт ex.what(). 
Например:
Код

catch ( const std::exception& ex )
{
   std::cout << ex.what();
}


PM MAIL   Вверх
Sartorius
Дата 23.11.2007, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1568
Регистрация: 18.7.2006
Где: Ivory tower

Репутация: 1
Всего: 37



 У меня 2003-я все работает. May be переустановить студию?
PM MAIL ICQ   Вверх
JackYF
Дата 23.11.2007, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: нет
Всего: 162



жестоко... ты уверен, что ты до работы с вектором нигде в памяти не накосячил?



--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Earnest
Дата 25.11.2007, 13:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(JackYF @  23.11.2007,  23:21 Найти цитируемый пост)
жестоко... ты уверен, что ты до работы с вектором нигде в памяти не накосячил?

скорее всего.
Еще одна возможная причина: DLL + разные экземпляры CRT (например, как статик в каждой DLL) - т.е. кривой проект.



--------------------
...
PM   Вверх
mantissa
Дата 26.11.2007, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



Приветствую всех откликнувшихся!

JackYF > жестоко... ты уверен, что ты до работы с вектором нигде в памяти не накосячил?
допустим, но слабо вериться, что вызов метода v.clear() непосредственно перед вставкой способен исправить то, что я накосячил в памяти

Earnest> Еще одна возможная причина: DLL + разные экземпляры CRT (например, как статик в каждой DLL) - т.е. кривой проект.
вызываемая функция действительно компилируется в DLL...
а можно поподробнее... про  разные экземпляры CRT и т.д.

глюки с DLL уже видел (но в другом проекте), похоже отладчик шел по DLL, созданной DEBUG, а показывал RELEASE версию, но когда очередной STEP вместо функции MessageBox() выполнял CONTINUE на начало цикла, я чуть с кресла не упал....

а насчет кода... попробую выжимки сделать....

файл1
...
namespace {
  ...
  vector <string> vcsErrInfo;
 ...
}
fun1
{
...
  case WM_TIMER:
   ...
   reread_data(hdlg);
   ...
}
fun reread_data()
{
    ...    
    ::vcsErrInfo.clear();
    mcr = get_ErrInfo(::vcsErrInfo);
   ...
}
file2
...
EXPORT int get_ErrInfo     (vector<string>&);
...

file3
EXPORT int get_ErrInfo(vector<string>&vcS)
{
    FILE *fil;
  $ CHAR    buf[2048];
  //$ CHAR    buf1[256];
    CHAR    szDop[256] = "zero";
  fil = fopen("get_ErrInfo.log", "a+");
  fprintf(fil, "%s\n", "=============================\n get_ErrInfo: started ...");
  fflush(fil);
$WHENEVER sqlerror goto ERROR_SQL;
  lstrcpy(szDop, "declare curs1 cursor");
  $declare curs1 cursor with HOLD for 
    select dt||" "||fg||" "||nfile||" "||code||"     %1%"||NVL(s_num,"--")||" %2%"||NVL(unum,"--")||" %3%"||NVL(line,"--")||" %4%"||NVL(pos,"--")||" %5%"||NVL(beg_line,"--")||' %6%'||NVL(text,"ОПИСАНИЕ ОТСУТСТВУЕТ")||' %7%'||NVL(kodmes,'---')
--    select extend(dt,hour to second)||" "||fg||" "||nfile||" "||code||" %1%"||s_num||" %2%"||NVL(unum,"--")||" %3%"||NVL(line,"--")||" %4%"||NVL(pos,"--")||" %5%"||NVL(beg_line,"--")||' %6%'||NVL(text,"ОПИСАНИЕ ОТСУТСТВУЕТ")
   -- NVL(s_num,"---")||" "||NVL(unum,"---")||" "||NVL(line,"---")||" "||NVL(pos,"---")||" "||NVL(beg_line,"---")||" "||NVL(text,"ОПИСАНИЕ ОТСУТСТВУЕТ") 
    from tmp_err_info 
    --WHERE inuse = '-'
    order by dt DESC, fg, nfile
    --FOR UPDATE OF inuse
    ;
  //lstrcpy(szDop, "BEGIN WORK");
  //$BEGIN WORK;
  lstrcpy(szDop, "$open curs1 cursor");
  $open curs1;
  vcS.clear();    // теперича здесь стоит чистка, чтоб работало....
  for (INT j=0; ; ++j)
  {
    lstrcpy(szDop, "fetch curs1 cursor");
    $fetch curs1 into :buf;
    if (SQLCODE == 100) break;
    RTrim(buf);
    fprintf(fil, "%03d)\n", j+1);
    fprintf(fil, "buf=>%s<\n", buf);
    fflush(fil);
    string sTemp = buf;
    fprintf(fil, "&vcS=%p (%p)\n", &vcS, vcS);
    vcS.push_back(sTemp);
    fprintf(fil, "%s\n", "push_back(sTemp=buf) Ok!");
    fflush(fil);
    //$UPDATE tmp_err_info 
    //  SET inuse = '+'
    //  WHERE CURRENT OF curs1;
  }
  lstrcpy(szDop, "close curs1 cursor");
  $close curs1;
  lstrcpy(szDop, "free curs1 cursor");
  $free  curs1;
  //lstrcpy(szDop, "COMMIT WORK");
  //$COMMIT WORK;
  fclose(fil);
  return 0;
//-----
$WHENEVER SQLERROR continue;
ERROR_SQL: 
  int mcr = SqlMyInfo("get_ErrInfo", szDop);
  $close curs1;
  $free curs1;
  fclose(fil);
  return mcr;
}
 не успел почистить.... сорри

PM MAIL   Вверх
JackYF
Дата 26.11.2007, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: нет
Всего: 162



mantissa, пользуйся кнопками "Код" и "Цитата".
Переформатируй сообщение, читать сложно.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
NiJazz
Дата 26.11.2007, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


Профиль
Группа: Экс. модератор
Сообщений: 2286
Регистрация: 10.8.2003
Где: Москва

Репутация: 2
Всего: 23



Цитата
а можно поподробнее... про  разные экземпляры CRT и т.д.

Память выделенная в одной куче, не может быть освобождена в другой. Как вариант, ты инициализируешь вектор какими-то значениями (выделяешь память), к примеру, в exe, а затем передаёшь вектор по ссылке или указателю в функцию DLL и там вызываешь vector::clear, то есть освобождаешь память. У exe и dll разная куча. 
Но в то же время, обычно в DEBUG-версии срабатывает ASSERT при подобных ошибках, а не исключение. Для проверки можешь использовать _CrtIsValidHeapPointer( &my_vector[0] ).

PM MAIL   Вверх
mantissa
Дата 27.11.2007, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



Цитата

Память выделенная в одной куче, не может быть освобождена в другой. Как вариант, ты инициализируешь вектор какими-то значениями (выделяешь память), к примеру, в exe, а затем передаёшь вектор по ссылке или указателю в функцию DLL и там вызываешь vector::clear, то есть освобождаешь память. У exe и dll разная куча. 
Но в то же время, обычно в DEBUG-версии срабатывает ASSERT при подобных ошибках, а не исключение. Для проверки можешь использовать _CrtIsValidHeapPointer( &my_vector[0] ).


ТОЧНО! отладчик застревал в кодах STL на попытке высвободить память.
а ведь я на похожие грабли уже наступал...
СПАСИБО Всем и персональное СПАСИБО NiJazz!

и... все равно появляется парочка вопросов....
1) а как же тогда ListBox (Control) справляется с вставкой и удалением своих строк из разных куч памяти (у него подобных проблем не замечал....)
2) чем чревато то, что объект создан в одной куче, а пользуется памятью чужой? (почему объект не извлекает ссылку на кучу в которой он создан, чтобы забирать память из той же кучи? может это настройки безопасности и их можно где-нибудь выставить в свойствах проекта? )

с ув. BSD
PM MAIL   Вверх
Fazil6
Дата 27.11.2007, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 3
Всего: 60



Цитата(mantissa @  27.11.2007,  16:32 Найти цитируемый пост)
 У exe и dll разная куча.

неверно. У exe и dll одна куча. Проблема кроется когда exe и dll скомпиллированы с разными версиями CRT и когда объект создается в одном модуле(одной версией CRT), а удаляется в другом модуле(другой версией CRT) получаем ошибку
PM MAIL   Вверх
mantissa
Дата 27.11.2007, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



Цитата

неверно. У exe и dll одна куча. Проблема кроется когда exe и dll скомпиллированы с разными версиями CRT и когда объект создается в одном модуле(одной версией CRT), а удаляется в другом модуле(другой версией CRT) получаем ошибку


опаньки.... и как енто проверить или еще лучше где это в MS VC 2003.net посмотреть?

с ув. BSD
PM MAIL   Вверх
Fazil6
Дата 27.11.2007, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 3
Всего: 60



вот так

Присоединённый файл ( Кол-во скачиваний: 12 )
Присоединённый файл  prop.JPG 55,92 Kb
PM MAIL   Вверх
mantissa
Дата 29.11.2007, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



Приветствую славную братию программистов!

Цитата

вот так

Присоединённый файл ( Кол-во скачиваний: 4 ) 


 в свойствах DLL стояло действительно вместо сингла мульти....
исправил на сингл...
результат тот же :

отладчик указывает на файл "vector"
Код

    iterator insert(iterator _Where, const _Ty& _Val)
        {    // insert _Val at _Where
        size_type _Off = size() == 0 ? 0 : _Where - begin();
        _Insert_n(_Where, (size_type)1, _Val);
        return (begin() + _Off);                                  // << сыпется здесь!
        }



может нужно какие-нибудь действия при присоединении DLL-ки делать?
или не использовать аллокатор по умолчанию в векторе, а назначать какой-нить свой??

в принципе проблема как бы замаскировалась, и про нее м. забыть, делая любые операции с вектором только "по ту сторону баррикад",
но я потратил почти 2 дня, пока не замаскировал проблему эмпирическим путем, а поскольку чудес в программировании не бывает и сейчас срочной работой не грузят, как раз есть время разобраться в этом "чуде"...

с ув. BSD
PM MAIL   Вверх
Fazil6
Дата 29.11.2007, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 3
Всего: 60



Цитата(mantissa @  29.11.2007,  16:37 Найти цитируемый пост)
 в свойствах DLL стояло действительно вместо сингла мульти....исправил на сингл...результат тот же :

надо не сингл, НАДО ЧТОБЫ ЭТОТ ПАРАМЕТР БЫЛ ОДИНАКОВЫЙ У ВСЕХ, у ддл и у ехе

.
Цитата(mantissa @  29.11.2007,  16:37 Найти цитируемый пост)
в принципе проблема как бы замаскировалась, и про нее м. забыть, делая любые операции с вектором только "по ту сторону баррикад",но я потратил почти 2 дня, пока не замаскировал проблему эмпирическим путем, а поскольку чудес в программировании не бывает и сейчас срочной работой не грузят, как раз есть время разобраться в этом "чуде"...

чуда здесь нет. Вообще передача между модулями объектов(в том числе и STL) не слишком хорошая идея.  
Цитата(mantissa @  29.11.2007,  16:37 Найти цитируемый пост)
может нужно какие-нибудь действия при присоединении DLL-ки делать?или не использовать аллокатор по умолчанию в векторе, а назначать какой-нить свой??

ничего тебе тут не поможет. Единственное рабочее решение в таком случае - использовать в ехе и dll один компиллятор, одной и той же версии с одинаковыми настройками. Во Всех других случаях  никаких гарантий работоспособности.


PM MAIL   Вверх
mantissa
Дата 30.11.2007, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



Привет, Fazil6 !

Цитата

надо не сингл, НАДО ЧТОБЫ ЭТОТ ПАРАМЕТР БЫЛ ОДИНАКОВЫЙ У ВСЕХ, у ддл и у ехе


были разные, теперь один... не помогает...
Цитата

использовать в ехе и dll один компиллятор, одной и той же версии с одинаковыми настройками.


дык один он... это вообще один Solution, в который включены 2 проекта (или как там они у него обзываются)....
да и на мой взгляд необходимости в DLL-ке вроде нет.... просто мой предшественник все, что относилось к ESQL/C решил засунуть в DLL

а почему передача параметров в DLL плохая идея и чем ссылка на объект хуже например указателя на строку?

а функции стараюсь писать универсальные, чтобы действительно эту DLL  м. было другими EXE-шниками использовать

и на мой взгляд проще передать объект, чтобы некто там напихал в него данные, используя его же методы, вместо того, чтобы пихать в объект методы, которые используют вызовы множества ESQL/C функций

стоп...
перейдем к конкретному примеру....
мне нужно отобразить содержимое файла, хранящееся в БД в BLOB-е и некоторые значения полей таблиц
рассмотрим варианты...
имеется универсальная функция уже написанная и откомпилированная...
 ты...
      1) просто ее вызовешь с необходимыми параметрами?
      2) скопируешь ее код в свой проект?
      3) напишешь нечто очень похожее, но свое?

как бы ты сам написал эту функцию?
  1) передал бы ей кучу хэндлов на окна и пущай в них сама все вставляет
  2) забрал бы от нее все данные в статические буфера (для BLOB например 1000К или больше) и сам бы повставлял данные
  3) то же но с динамическими буферами (string, vector и т.д.) (кстати вариант там распределять память, а здесь при закрытии окна освобождать - также не проходит по тем же причинам, приходиться выполнять лишние запросы для уточнения размеров)

поделись плиз логикой...

с ув. BSD
 
PM MAIL   Вверх
Fazil6
Дата 30.11.2007, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 3
Всего: 60



Цитата(mantissa @  30.11.2007,  17:10 Найти цитируемый пост)
а почему передача параметров в DLL плохая идея и чем ссылка на объект хуже например указателя на строку?

я говорил о объектах классов. Если у тебя в интерфейсе dll функция, которая в качестве праметра принимает к примеру std::map,  то как ты эту функцию будешь вызывать, скажем, в Delphi ? Причем, не факт даже, что программа компиллируемая С++ компиллятором всегда сможет работать с такой dll, просто потому что использует какую-нибудь другую версию STL, потому что объект std::list создаваемый ею отличается в силу особеностей компиллятора от объекта создаваемого компиллятором dll. Объект класса - это ведь не int какой-нибудь.
Цитата(mantissa @  30.11.2007,  17:10 Найти цитируемый пост)
а функции стараюсь писать универсальные, чтобы действительно эту DLL  м. было другими EXE-шниками использовать

для этой цели нужно использовать переносимые типы в интерфейсе dll. Использование классов резко сужает область применимости такой библиотеки.
Цитата(mantissa @  30.11.2007,  17:10 Найти цитируемый пост)
и на мой взгляд проще передать объект, чтобы некто там напихал в него данные, используя его же методы, вместо того, чтобы пихать в объект методы, которые используют вызовы множества ESQL/C функций

см. выше. 
Для того чтобы напихать в твой объект вызывающий должен знать что это такое и правильно его использовать

насчет задачи твоей... Постановка слишком неконкретная. Впринципе возможны любые из приведенных тобой вариантов. Причем здесь dll? Если уж рассматривать некие варианты, то если есть некая либа, которая инкапсулирует, допустим, работу с БД, то функция чтения значения из BLOB записывала бы результат в некий буфер unsigned char* но это далеко не единственное возможное и приемлемое решение. В каждом конкретном случае я буду решать как удобне. У меня тоже есть проекты, которые содержат модули с интерфейсом использующим STL объекты. 
PM MAIL   Вверх
NiJazz
Дата 30.11.2007, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


Профиль
Группа: Экс. модератор
Сообщений: 2286
Регистрация: 10.8.2003
Где: Москва

Репутация: 2
Всего: 23



Цитата
неверно. У exe и dll одна куча

В данном случае, разная.
Не нужно пытаться исправлять ошибку просто обойдя проблему - выставить одинаковый рантайм. Просто не надо выпускать наружу контейнеры STL и всё тут. Используйте копирование, тогда и проблем не будет.

Добавлено через 3 минуты и 1 секунду
Об отладочной куче можно почитать здесь
PM MAIL   Вверх
mantissa
Дата 3.12.2007, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



Привет Все!

Согласен с NiJazz по поводу того, что в 32 битной ОС кучи будут разные, но все равно не понимаю, в чем проблема освободить занимаемую память любой кучи, похоже что для безопасности процессов запрещают насильственными методами (ОС д.б. абсолютно все равно)

и второе... что плохого, что вектор находиться в одной куче и содержит объекты, хранящиеся в другой куче?


Цитата(Fazil6 @  30.11.2007,  18:45 Найти цитируемый пост)
... допустим, работу с БД, то функция чтения значения из BLOB записывала бы результат в некий буфер unsigned char* ...  


кто будет распределять память под буфер???
 с целью оптимизации было бы выгоднее, чтобы модуль сам распределял память (он то знает какого размера BLOB) (заодно бы и сообщения ползунку слала бы о ходе загрузки),  а программа бы в конце высвобождала по этому unsigned char* память. Но так не работает!

кстати отказаться от DLL начинает все больше привлекать меня smile (видно не дорос еще я до них)

с ув. BSD

PM MAIL   Вверх
mantissa
Дата 4.12.2007, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 25
Регистрация: 23.10.2007

Репутация: 1
Всего: 1



привет Всем!

более внимательное тестирование показало, что я был не прав, утверждая, что std::string работает без проблем по ссылке в DLL модуле.
НИЧЕГО не работает. Ни один объект динамически перераспределяющий память не будет корректно работать с другим потоком

учту ошибки в будущем. Всем СПАСИБО!

с ув. BSD
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.1364 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.