POD vs delete []
От: PowerUserX  
Дата: 24.06.16 08:31
Оценка: +1 -2 :)))
Доброго всем.
Что то вчера навеяло читал мельком на хабре про с++ стат.анализ.

Пишут — этот код некорректный
std::shared_ptr<int> ss(new int[decks * 52]);


Предупреждение PVS-Studio: V554 Incorrect use of shared_ptr. The memory allocated with 'new []' will be cleaned using 'delete'. BlackJack_Server140 table.cpp 471

Надо заменить на
std::shared_ptr<int> ss(new int[decks * 52], std::default_delete<int[]>());


Я просто когда пишу знаю что тут у меня тип POD, и не делаю delete [], все равно то new->malloc, delete[]->free
И главное — я знаю где POD, а где конструктор, т.е. детской ошибки не получу

А что вы думаете — просто поразмышлять

P.S. Да еще при компиляции
delete []
время требует наверное больше?? Хотя утверждать не буду.
Re: POD vs delete []
От: uzhas Ниоткуда  
Дата: 24.06.16 08:40
Оценка: +8
Здравствуйте, PowerUserX, Вы писали:

PUX>Пишут — этот код некорректный

правильно пишут

PUX>А что вы думаете — просто поразмышлять

я думаю, что обязательно соблюдать парность new[]/delete[], иначе это UB (сегодня для POD работает любой вариант, завтра не работает. сегодня это POD — завтра не POD) и говорит о непрофессионализме разработчика

PUX>P.S. Да еще при компиляции
delete []
время требует наверное больше??

не слышал о таком и не вижу причин для этого
Re: POD vs delete []
От: VTT http://vtt.to
Дата: 24.06.16 09:10
Оценка:
new->malloc, delete[]->free — это крайне грубые ошибки.
Сегодня вы знаете где POD, а завтра кто-то заменит этот POD на не POD и вы все вместе сядите в лужу.
Освобождающий память метод всегда должен соответствовать методу, выделившему ее, так что диагностика однозначно полезная.

На скорость компиляции это все никаким заметным образом не влияет.
Хотя страдальцам, у которых все часами компилируются, будет не легче.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Отредактировано 24.06.2016 9:20 VTT . Предыдущая версия . Еще …
Отредактировано 24.06.2016 9:15 VTT . Предыдущая версия .
Отредактировано 24.06.2016 9:14 VTT . Предыдущая версия .
Re[2]: POD vs delete []
От: uzhas Ниоткуда  
Дата: 24.06.16 09:17
Оценка:
Здравствуйте, VTT, Вы писали:

VTT>А вот кусок

VTT>
std::shared_ptr<int> ss(new int[decks * 52], std::default_delete<int[]>());

VTT>даже не соберется, так как не все параметры шаблона указаны.

у shared_ptr один шаблонный параметр, см. http://en.cppreference.com/w/cpp/memory/shared_ptr
то, о чем вы пишете, актуально для std::unique_ptr. в нем явно надо указать тип deleter-а, в shared_ptr используется type-erasure и надобности указывать тип deleter-а нет
Re[3]: POD vs delete []
От: VTT http://vtt.to
Дата: 24.06.16 09:20
Оценка:
Кстати да, это как раз еще один повод не воздержаться от использования shared_ptr.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[2]: POD vs delete []
От: PowerUserX  
Дата: 24.06.16 09:27
Оценка: -1
Здравствуйте, uzhas, Вы писали:

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


PUX>>Пишут — этот код некорректный

U>правильно пишут

PUX>>А что вы думаете — просто поразмышлять

U>я думаю, что обязательно соблюдать парность new[]/delete[], иначе это UB (сегодня для POD работает любой вариант, завтра не работает. сегодня это POD — завтра не POD) и говорит о непрофессионализме разработчика

PUX>>P.S. Да еще при компиляции
delete []
время требует наверное больше??

U>не слышал о таком и не вижу причин для этого


POD — это просто память, кусок выделил — занулил — использовал — удалил
Пока есть текущая память = true || false — наши программы на С++ компилятся

А вот если мы переедем на квантовый компьютер — то наши программы не скомпилятся
там другая модель памяти

Так что POD был ... есть ... и будет есть
Re: POD vs delete []
От: K13 http://akvis.com
Дата: 24.06.16 09:35
Оценка: +3
PUX>Я просто когда пишу знаю что тут у меня тип POD, и не делаю delete [], все равно то new->malloc, delete[]->free

А потом кто-то добавляет в проект навороченный аллокатор, который по-разному обрабатывает malloc и new[] -- и приплыли.
или кто-то переопределил new / delete но не стал трогать malloc / free -- и опять чудеса.
нет уж, парность надо соблюдать
Re: POD vs delete []
От: Constructor  
Дата: 24.06.16 09:48
Оценка: 5 (1)
Здравствуйте, PowerUserX, Вы писали:

PUX>Пишут — этот код некорректный

PUX>
PUX>std::shared_ptr<int> ss(new int[decks * 52]);
PUX>


Сюда так и просится специализация std::unique_ptr для работы с массивами:

template
    <
        class T,
        class Deleter
    >
class unique_ptr<T[], Deleter>;


Тем более, что создания такого умного указателя предусмотрена специальная перегрузка функции std::make_unique:

template< class T >
unique_ptr<T> make_unique( std::size_t size );


Пример:

auto array = std::make_unique<int[]>(42);


Здесь создается объект array класса std::unique_ptr<int[]>, хранящий указатель на динамический массив из 42 элементов типа int. Эдакая легковесная замена std::dynarray.
Re: POD vs delete []
От: Erop Россия  
Дата: 24.06.16 10:13
Оценка:
Здравствуйте, PowerUserX, Вы писали:

PUX>Я просто когда пишу знаю что тут у меня тип POD, и не делаю delete [], все равно то new->malloc, delete[]->free

PUX>И главное — я знаю где POD, а где конструктор, т.е. детской ошибки не получу

Такой гарантии нет. То, что текущая версия твоего компилятора и Фреймворка это позволяет, ничего не гарантирует...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: POD vs delete []
От: Erop Россия  
Дата: 24.06.16 10:15
Оценка:
Здравствуйте, uzhas, Вы писали:

U>то, о чем вы пишете, актуально для std::unique_ptr. в нем явно надо указать тип deleter-а, в shared_ptr используется type-erasure и надобности указывать тип deleter-а нет

Но таки надо передать в конструктор делетер массива...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: POD vs delete []
От: Erop Россия  
Дата: 24.06.16 10:18
Оценка: +1
Здравствуйте, PowerUserX, Вы писали:

PUX>POD — это просто память, кусок выделил — занулил — использовал — удалил

Ну так и выделяй по alloc, а освобождай по free

PUX>Так что POD был ... есть ... и будет есть


Проблема в том, что кто-то, включая автором стандартной библиотеки для твоего компилятора, могут наделить operator new[] и operator delete[] каким-то особым поведением. Например, могут класть куда-то ПЕРЕД буфером его длину или число элементов в new[], а в delete[] это как-то использовать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: POD vs delete []
От: Stanislav V. Zudin Россия  
Дата: 24.06.16 10:24
Оценка: +3
Здравствуйте, PowerUserX, Вы писали:

PUX>Пишут — этот код некорректный

PUX>
PUX>std::shared_ptr<int> ss(new int[decks * 52]);
PUX>


А у меня другой вопрос. Так сказать, для расширения кругозора. Почему не std::vector<int>?
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: POD vs delete []
От: Lexey Россия  
Дата: 24.06.16 11:00
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>А у меня другой вопрос. Так сказать, для расширения кругозора. Почему не std::vector<int>?


Или не boost::shared_array?
"Будь достоин победы" (c) 8th Wizard's rule.
Re[2]: POD vs delete []
От: Erop Россия  
Дата: 24.06.16 11:16
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>А у меня другой вопрос. Так сказать, для расширения кругозора. Почему не std::vector<int>?

Наверное потому, что он shared не умеет...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: POD vs delete []
От: PowerUserX  
Дата: 24.06.16 11:18
Оценка: -1
Здравствуйте, Erop, Вы писали:

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


PUX>>POD — это просто память, кусок выделил — занулил — использовал — удалил

E>Ну так и выделяй по alloc, а освобождай по free

PUX>>Так что POD был ... есть ... и будет есть


E>Проблема в том, что кто-то, включая автором стандартной библиотеки для твоего компилятора, могут наделить operator new[] и operator delete[] каким-то особым поведением. Например, могут класть куда-то ПЕРЕД буфером его длину или число элементов в new[], а в delete[] это как-то использовать...


Проблемы нет, перед пусть кладут что угодно
Все API Linux, Win, OsX .... аперирует входными параметрами (char* pBuff, int len ) — и это POD — плоская память
И это на наших компах будет всегда — для кубитов в квантовом компе енто не покатит

Вот поэтому
Мне иногда короче писать
auto pBuffer = new int[32];
char* pBuffer = (char*)malloc(32 * sizeof(int));
^
|
| — тут длиннее

и вот зачем мне писать delete [] pBuffer ?

P.S. Честно я все это писал немного шоб потролить — у нас тут все крутые
Ночью разбуди
— Что написано в стандарте на странице 485?
— .....
длиннее иногда всё-таки лучше ;)
От: Erop Россия  
Дата: 24.06.16 12:25
Оценка: +1
Здравствуйте, PowerUserX, Вы писали:

PUX>Проблемы нет, перед пусть кладут что угодно

Смотри, ты попросил в new int[32] 128 байт памяти, а operator new[] взял, да и выделил 132. В первые 4 положил что-то там своё, а тебе вернул адрес пятого (то есть реальный адрес блока + 4)
Если ты позовёшь с эти адресом operator delete[], то он 4 вычтет, свои данные найдёт и всё правильно сделает. В том числе и освободит ВЕСЬ блок.
А если ты позовёшь operator delete, то он просто освободит часть блока, вернее попытается, и всё...

То есть ситуация получится примерно такая:
struct XXX { 
    int hiddenField;
    int array[32];
};
int* array = new XXX->array;
delete array; // Упс


PUX>auto pBuffer = new int[32];

PUX>char* pBuffer = (char*)malloc(32 * sizeof(int));
PUX> ^
PUX> |
PUX> | — тут длиннее

PUX>и вот зачем мне писать delete [] pBuffer ?

Ну успехов тебе в труде. Не забудь прислать этот пример оригинальности и свежести своего мышления в своё партфолио и приложить к резюме, когда будешь искать след. работу...

PUX>P.S. Честно я все это писал немного шоб потролить — у нас тут все крутые

Я уже что-то начал подозревать
Держись в общем тут, и хорошего тебе настроения
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: POD vs delete []
От: B0FEE664  
Дата: 24.06.16 12:32
Оценка:
Здравствуйте, Erop, Вы писали:

SVZ>>А у меня другой вопрос. Так сказать, для расширения кругозора. Почему не std::vector<int>?

E>Наверное потому, что он shared не умеет...

std::shared_ptr<std::vector<int>> ss(new std::vector<int>(decks * 52));



PS Хотя, конечно, new надо на std::make_shared заменить:

auto ss = std::make_shared< std::vector<int> >(decks * 52);
И каждый день — без права на ошибку...
Re[6]: POD vs delete []
От: PowerUserX  
Дата: 24.06.16 12:53
Оценка: :)
Здравствуйте, Erop, Вы писали:

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


PUX>>Проблемы нет, перед пусть кладут что угодно

E>Смотри, ты попросил в new int[32] 128 байт памяти, а operator new[] взял, да и выделил 132. В первые 4 положил что-то там своё, а тебе вернул адрес пятого (то есть реальный адрес блока + 4)
E>Если ты позовёшь с эти адресом operator delete[], то он 4 вычтет, свои данные найдёт и всё правильно сделает. В том числе и освободит ВЕСЬ блок.
E>А если ты позовёшь operator delete, то он просто освободит часть блока, вернее попытается, и всё...

Согласен.

E>То есть ситуация получится примерно такая:
struct XXX { 
E>    int hiddenField;
E>    int array[32];
E>};
E>int* array = new XXX->array;
E>delete array; // Упс


PUX>>auto pBuffer = new int[32];

PUX>>char* pBuffer = (char*)malloc(32 * sizeof(int));
PUX>> ^
PUX>> |
PUX>> | — тут длиннее

PUX>>и вот зачем мне писать delete [] pBuffer ?

E>Ну успехов тебе в труде. Не забудь прислать этот пример оригинальности и свежести своего мышления в своё партфолио и приложить к резюме, когда будешь искать след. работу...

Надо ж както развлекаться — а то сгоришь

PUX>>P.S. Честно я все это писал немного шоб потролить — у нас тут все крутые

E>Я уже что-то начал подозревать
E>Держись в общем тут, и хорошего тебе настроения
Re[4]: POD vs delete []
От: Erop Россия  
Дата: 24.06.16 13:17
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>PS Хотя, конечно, new надо на std::make_shared заменить:


BFE>
BFE>auto ss = std::make_shared< std::vector<int> >(decks * 52);
BFE>


Это, какой-то недописсемизированный вариант, я щитаю...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: POD vs delete []
От: B0FEE664  
Дата: 24.06.16 15:55
Оценка: :)
Здравствуйте, Erop, Вы писали:

BFE>>PS Хотя, конечно, new надо на std::make_shared заменить:


BFE>>
BFE>>auto ss = std::make_shared< std::vector<int> >(decks * 52);
BFE>>

E>Это, какой-то недописсемизированный вариант, я щитаю...

Точно! Надо так:
BFE>>
BFE>>auto&& ss = std::make_shared< std::vector<int> >(decks * 52);
BFE>>
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.