[C++] Вопрос по распределению памяти

Serega009

Может, некорректно сформулировал тему...
Вопрос в следующем.
У меня есть функция:
void myFunc
{
MyClass obj(some, arguments);
. . .
}
Правильно ли я понимаю, что после её отработки будет вызван деструктор MyClass' а?
А что происходит если функцию модифицировать следующим образом:
void myFunc
{
MyClass *obj = new MyClass(some, arguments);
. . .
}
?
На самом деле, я написал свой класс, но в первом варианте программа "выполняет недопустимую операцию", а во втором варианте функция один раз отрабатывает нормально (без ошибок а во второй раз вообще не отрабатывает (программа вылетает).
Не знаю, что ещё тут сказать... могу выложить исходник всего проекта (около 150 кило) и описать вкратце как он устроен.
ЗЫ
Не издевайтесь, я в C++ не сильно шарю — пишу чисто для себя (для своего удовольствия).

Devid

В первом случае деструктор будет вызван, во втором нет. Скорее всего проблема в MyClass.
И что ты передаешь в конструктор?

Serega009

Я собственно, подозреваю, что проблема в деструкторе MyClass'а.
Конструктор объявлен так:
MyClass(long, constr char*)
Создаю так
MyClass obj(28, "string containing 28 chars");

Serab

Учитесь пользоваться отладчиком, это еще никому не повредило.

Devid

Да, поставь брейкпойнт в деструкторе. Не считая грамматической ошибки в конструкторе ничего подозрительного.

Serega009

А нет, вру. Если в функции создаю ссылку на объект, то функция отрабатывает нормально каждый раз, но результат (с одними и теми же данными, то есть аргументами переданными в конструктор) рандомный, хотя класс создаётся исходя только из аргументов, переданных в конструктор.

Serega009

Имеешь ввиду, что нужно было поставить const перед long?
Вообще, конструктор объявлен так:
MyClass(long size, const char* str)

Devid

* это указатель. & это ссылка. Так ссылку или указатель?

valodyr

Где-то в объекте класса хранится левый указатель, и освобождается в деструкторе. Проверять надо, скорее всего, как раз конструктор. А вообще, телепаты вроде как в отпуске опять, было бы неплохо увидеть код класса.

Serega009

Класс зовётся wbenData. Там используется парочка классов из wxWidgets.

Serab

Не считая грамматической ошибки в конструкторе ничего подозрительного.
Лично мне кажется подозрительным, что в нагрузку к const char * передается длина.

margadon

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

Devid

На какой строчке падает?

Serega009

Вот функция, которую написал для теста класса:
bool wtfTorrentTab::ProcessSingle
{
wbenData data(3, "i1e");
int error = data.error;
wxString msg;
switch (error)
{
case 0:
break;
case W_BENCODE_ERROR_UNKNOWN_DATA_TYPE:
msg = wxT("Error: Unknown data type");
break;
case W_BENCODE_ERROR_UNEXPECTED_TOKEN:
msg = wxT("Error: Unexpected token");
break;
case W_BENCODE_ERROR_NO_END_TAG:
msg = wxT("Error: No end tag");
break;
case W_BENCODE_ERROR_ODD_ELEMENTS_IN_DICTIONARY:
msg = wxT("Error: Odd element in dictionary");
break;
case W_BENCODE_ERROR_INVALID_KEY:
msg = wxT("Error: Invalid key (should be a string)");
break;
default:
msg.Printf(wxT("Error: Unknown error %d" error);
break;
}
if (error == 0)
{
msg = DumpData(data);
}
wxMessageBox(msg, wxT("Bencode" wxOK);
return true;
}

wxString wtfTorrentTab::DumpData(wbenData data)
{
wxString res;
wbenDataDictionary::iterator it;
wbenDataDictionary *dict;
wbenDataList *arr;
size_t i, j;

switch (data.GetType
{
case wbenDATA_UNDEFINED:
res = wxT("undef");
break;
case wbenDATA_INTEGER:
res.Printf(wxT("%d" *(data.GetValue.m_int;
break;
case wbenDATA_STRING:
res = wxT("'") + *(data.GetValue.m_str) + wxT("'");
break;
case wbenDATA_LIST:
res = wxT("[");
arr = data.GetValue.m_list;
for (i = 0; i < arr->Count; i++)
{
res += wxT("\n");
res += DumpData(arr->Item(i;
res += wxT(",");
}
res += wxT("]");
break;
case wbenDATA_DICTIONARY:
res = wxT("{");
dict = data.GetValue.m_dict;
for (it = dict->begin; it != dict->end; ++it)
{
res += wxT("\n");
res += wxT("'") + it->first + wxT("' => ");
res += DumpData(*(it->second;
res += wxT(",");
}
res += wxT("}");
break;
default:
res = wxT("Unknown data type");
break;
}
return res;
}
Вылетает, по-видимому, при выходе из функции — сообщение выдаётся, а после того, как нажмёшь кнопку "Ok", выдаётся сообщение винды с предложением отослать отчёт..

Serab

Вылетает, по-видимому, при выходе из функции — сообщение выдаётся, а после того, как нажмёшь кнопку "Ok", выдаётся сообщение винды с предложением отослать отчёт..
у меня такое недавно было когда переносил подсистему с ANSI на Unicode. В одном месте забыл передать меньшую длину (в два раза функция wcscpy затирала много лишней памяти и в том числе запарывала стек. Очень неприятная ошибка, трудно найти причину. Хотя здесь и в деструкторе может быть ошибка. Попробуй заключить весь код этой функции в фигурные скобки, за ними же оставь MessageBox и return.

Devid

После выхода вызывается деструктор ~wbenData. Поставь в нем брейкпойнт и скажи, на какой строчке деструктора падает и доходит ли вообще до него.
Если не можешь поставить брейкпойнт, то можно после каждой строчки что-нибудь выводить и так понять, где падает. Хотя это не очень хороший способ.

Dasar

wbenData data(3, "i1e");
ты помнишь, что тут строка длины 4, а не 3?

Serab

ты помнишь, что тут строка длины 4, а не 3?
массив длины 4, строка - 3

Serega009

Э! А подскажите, плиз, как отладчиком пользоваться в Borland C Builder' е 6?
Я просто пишу в Far' е, а для компиляции пользуюсь makefile'ом.

Dasar

массив длины 4, строка - 3
такое деление - это все от лукавого... :)
главное, что какой-нибудь strcpy - поменяет 4 байта, а не 3

Serab

пишу чисто для себя (для своего удовольствия)
вот это в некотором роде не согласуется с последним постом.

Serab

главное, что какой-нибудь strcpy - поменяет 4 байта, а не 3
ну а strlen вернет 3, а не 4 =)

Serega009

Параметр size у меня используется только внутри класса и никуда более не передаётся. А смысл его такой, что обрабатываются первые size байт строки str.

kokoc88

DumpData(wbenData data)
Попробуй поставить там wbenData& data

Serab

wbenData& data
сначала const wbenData& data, потом если не откомпилиться, подумать.

kokoc88

сначала const wbenData& data, потом если не откомпилиться, подумать.
Нет, сразу wbenData& data, потому что надо смотреть котт автора.

Serab

Нет, сразу wbenData& data
Ну давай, советуй-советуй, я мешать не буду.

Serega009

Респект, заработало.
Объяснишь, в чём ошибка?
Пробовал закомментить строки, где DumpData вызывала себя рекурсивно, но ошибка возникала всё равно...

Serab

смотреть котт автора
И что ты там такого увидел. Что Get-методы не описаны как const?

kokoc88

Объяснишь, в чём ошибка?
Если заработало, значит, была проблема в копировании данных. Ты передавал класс wbenData по значению, это приводит к полному копированию его данных. При этом при выходе из функции вызывается деструктор, который удаляет все указатели. Поскольку указатели одинаковые в оригинале и в копии, деструктор оригинала пытается получить доступ к уже освобождённой памяти.
Тебе стоит прочитать что-нибудь по теме конструкторов копирования.
Оставить комментарий
Имя или ник:
Комментарий: