Должен ли я «удалить» этот CDC? - PullRequest
1 голос
/ 19 мая 2010

Folks, Я пытаюсь отследить прерывистую ошибку, которая появляется на сайте. У меня такое чувство, что в каком-то коде GDI я бы собрал все вместе, чтобы заставить работать принтер печати. ​​

Я не уверен, как удалить этот CDC, мой код выглядит нормально для меня, но это правильно.

// Create a device context for printing
CDC* dc = new CDC();
    if(! dc->CreateDC(safeDriverName.AsBSTR(), safePrinterName.AsBSTR(), NULL, NULL))
{
     throw . . . 
}

// as I finish with the CDC
dc->DeleteDC();
delete dc;

Нужно ли delete dc после dc->DeleteDC();?

Спасибо

Ответы [ 3 ]

9 голосов
/ 19 мая 2010

Поскольку вы выделили dc в куче, да, вам действительно нужно удалить dc. И не только это, но если вы сохраняете код таким, какой он есть, у вас также должен быть delete dc до вашего броска. Функция DeleteDC не связана с выделенной памятью dc.

Вы могли бы упростить это, хотя:

// Create a device context for printing
CDC dc;
if(! dc.CreateDC(safeDriverName.AsBSTR(), safePrinterName.AsBSTR(), NULL, NULL))
{
     throw . . . 
}

// as I finish with the CDC
dc.DeleteDC();

Обновление: Как упоминал @Fred, деструктор CDC позвонит вам DeleteDC().

5 голосов
/ 19 мая 2010

Мне нравится ответ Брайана. Но если по какой-то причине желательно динамическое распределение (возможно, проблемы с пространством в стеке), используйте умный указатель. Я бы, вероятно, предпочел boost :: scoped_ptr, но auto_ptr было бы достаточно:

// Create a device context for printing
auto_ptr<CDC> dc(new CDC());
    if(! dc->CreateDC(safeDriverName.AsBSTR(), safePrinterName.AsBSTR(), NULL, NULL))
{
     // dc is automatically cleaned up on the throw
     throw . . . 
}

// dc is automatically cleaned up at scope exit
0 голосов
/ 20 мая 2010

Выделение объекта CDC в куче для экономии памяти стека - это смешно! (прости меня за грубый язык).

Это небольшой объект, всего 16 байтов (в архитектуре Win32). Это просто 4 "целочисленных" переменных. На самом деле можно работать с необработанным HDC (который является только одним «целым числом»), однако для оболочки MFC по некоторым причинам определены еще 3 переменные.

Выделение памяти в куче, кроме ненужного кода, приводит к серьезному снижению производительности. Также он имеет значительные накладные расходы памяти, плюс вам нужна еще одна переменная (указатель на выделенную память). Так что общая потеря памяти - это гораздо больше. Кроме того, при работе с указателем на динамически распределяемые данные у вас фактически возникает дополнительная косвенность.

Нужно беспокоиться о потреблении слишком большого количества стековой памяти, если выделенные объекты имеют размер, сопоставимый с общим размером доступного стека. Скажем, на Win32 с размером стека потока по умолчанию 1 МБ я бы беспокоился о выделении объектов, начиная с десятков КБ. Или, в качестве альтернативы, вам следует беспокоиться, если вы широко используете глубокую рекурсию (тогда все выделенные локальные переменные умножаются на глубину рекурсии).

Но выделение 16 байтов «для экономии памяти стека» - это звучит безумно по сравнению с ужасным снижением производительности, сложностью кода, фрагментацией памяти и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...