Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: std::copy от VC++ 9: параноики в Microsoft?  (Прочитано 15018 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« : 16-04-2010 09:15 » 

Сегодня в 9-ке получил вот такое при попытке копирования контейнера в динамический массив:
Цитата
3>.\Matrix.cpp(28) : warning C4996: 'std::copy': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
3>        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility(2550) : see declaration of 'std::copy'


Вопрос: это что, теперь динамические массивы напрямую настоятельно не рекомендуются? В 8-ке такой паранойи не помню.
Сначала strcat-ы были deprecated, теперь вот это. В 10-ке операторы new[] и delete[] ещё warning-и не выдают?  Улыбаюсь

Я, конечно, понимаю всю глубину заботы о чужих кривых руках. Но когда руки достаточно прямые, или нет возможности обойти кривизну уже имеющегося решения - то такие вещи раздражают.
И тем более, не спасают от кривизны рук. Допустим, сегодня я занесу эту директиву SCL_SECURE_NO_WARNINGS, чтобы компилятор не наезжал на правильный код, а завтра кто-то (хоть бы и я сам) напишет кривой код, а предупреждение-то уже подавлено. Получается, этакий очень навязчивый и неудобный сервис: всё время пользоваться - плохо, отказываться - тоже не очень.

Пока единственный способ жить с этим, который я вижу, такой.
Перед релизом или при багах отрубать все такие директивы и смотреть ворнинг за ворнингом, делая полное ревью кода. Или делать специальные конфигурации с подавлением и без подавления предупреждений. В любом случае, жизнь проще как-то не становится Улыбаюсь
На такие вещи сложно полагаться, потому что в любой момент кривые руки могут испортить настройки, и тогда ты действуешь на основании неверных представлений о ситуации.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 16-04-2010 09:28 » 

Начиная с 2005 студии в таких случаях можно (и нужно) пользоваться безопасными аналогами:
http://msdn.microsoft.com/en-us/library/aa985872(v=VS.80).aspx
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 16-04-2010 10:16 » 

Но это же не стандарт - а если код потом ещё портировать? (не говоря уже о том, что секьюрные функции заметно ухудшают читаемость кода, а проблему кривых рук и неправильного размера целевого буфера практически не решают)
« Последнее редактирование: 16-04-2010 10:19 от Вад » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 16-04-2010 10:53 » 

Эммм... Я думаю тут дело не в стандарте, а в подходе разработчиков студии, которые решили себя лишний раз оградить от возможных проблем. Ведь это предупреждение ты получаешь только компилируя код в студии начиная с версии 8. Те на остальных остаётся и проблема и отсутствие предупреждения.
Если тебя это устраивает, то просто подавляй в студии >= 8 это сообщение и всё. А рядом с define поставь толстый коментарий, что оторвёшь голову по самые лодыжки тому, кто его изменит. Ага

зы Проблему кривых рук никакие ф-ции не исправят. Речь идёт о чистом завершении программы содержащий "кривой" код, чем могут ессно воспользоваться недоброжелатели. Попробуй выполнить программу с двумя разными вариантами и увидишь разницу:

Код:
#include <string>
#include <iostream>

int main( )
{
    using namespace std;
    
    string str("Hello World");
    const int array_size = 20;
    char myarray[array_size] = { 0 };
    basic_string<char>:: pointer arrayPtr = myarray;

    basic_string<char>::size_type nArray;

    //nArray = str._Copy_s(arrayPtr, array_size, 50);
nArray = str.copy(arrayPtr, array_size, 50);
   
    return 0;
}
« Последнее редактирование: 16-04-2010 11:32 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 16-04-2010 12:26 » 

В приведённом коде корректный array_size. То есть, решается ровно половина проблемы - причём, в случае std::copy это совсем не та половина. Да, копируется не больше, чем указано в качестве dest_size. Но если dest_size неверное (взять вместо array_size 50) - то последствия будут ровно те же.

Получается, просто принуждают своими руками написать: "я собираюсь копировать n-байтовый кусок в n-байтовый массив" - тем самым меня хотят мотивировать убедиться, действительно ли целевой массив нужного размера. По-моему, ошибка на этапе вычисления этого размера ничуть не меньше вероятна, чем ошибка слишком большого размера источника. А после того, как функция стала "более секьюрной", бдительность может быть потеряна ещё быстрее.
« Последнее редактирование: 16-04-2010 12:31 от Вад » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 16-04-2010 13:35 » 

Хммм. Не совсем понял array_size 50. У меня абсолютно одинаковое поведение: с copy вылетает, с _Copy_s завершается нормально.

Ещё раз, речь не об исправлении корявых ручек программера. Их только могила исправит. А вот устранить угрозу безопасности при вылетании проги, вот что они делают.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 16-04-2010 13:47 » 

например,
Код:
    using namespace std;
    
    string str("Hello World! This is a long long string, longer than 20 chars");
    const int array_size = 20;
    char myarray[array_size] = { 0 };
    basic_string<char>:: pointer arrayPtr = myarray;

    basic_string<char>::size_type nArray;

    nArray = str._Copy_s(arrayPtr, 50, 50);

Суть в том, что угроза устраняется только в половине случаев: когда всё ОК с размером цели. Если я точно отдаю себе отчёт об этом размере, то и копирование, скорее всего, сделаю аккуратно. Если же я забыл про размер цели, то ошибка с вылетом никуда не денется. При этом добавление ещё одной автоматической проверки на уровне стиля кодирования ("Давайте использовать эту новую безопасную функцию!") скорее ведёт к снижению уровня бдительности и появлению вот таких ошибок, которые потом будет ещё сложнее найти.

То есть, я, даже если буду сильно нетрезв, скорее всего не допущу ни той, ни другой ошибки. Но если я и забуду про то, что исходные данные могут не поместиться в цель - это скорее всего будет означать то, что я не уверен в размере этой цели. От кривых рук, воистину, ничто не спасёт Улыбаюсь
« Последнее редактирование: 16-04-2010 13:51 от Вад » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #7 : 16-04-2010 14:07 » 

Великолепно завершается твой код. Как и надо для безопасного завершения.

Наверное ты не понял. Прога вылетит в обоих случаях это факт. Но КАК вылетит? Вот в чём вопрос. В случа с copy она вылетает с точкой останова в ф-ции
_Myt& __CLR_OR_THIS_CALL assign(const _Myt& _Right, size_type _Roff, size_type _Count) и я как злоумышленик могу этим воспользоваться.

В случае использования _Copy_s прога завершается с точкой выхода в конце проги, и я отдыхаю. Это ж проблема Nr 1 при переполнении буфера.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 16-04-2010 14:36 » 

С какой стати они должны по-разному завершаться?
Код:
_SCL_INSECURE_DEPRECATE
size_type __CLR_OR_THIS_CALL copy(_Elem *_Dest,
size_type _Count, size_type _Off = 0) const
{ // copy [_Off, _Off + _Count) to [_Dest, _Dest + _Count)

 #if _HAS_ITERATOR_DEBUGGING
if (_Count != 0)
_DEBUG_POINTER(_Dest);
 #endif /* _HAS_ITERATOR_DEBUGGING */

// assume there is enough space in _Ptr
return _Copy_s(_Dest, _Count, _Count, _Off);
}
Происходит фактически одно и то же, и даже функция в итоге вызывается одна и та же, и в данном случае - с одними и теми же аргументами. Та самая _Copy_s.
« Последнее редактирование: 16-04-2010 14:38 от Вад » Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 16-04-2010 15:46 » 

Вад, я вот тоже к таким функциям отношусь с грустью. Это видимо для тех, кто не может написать
Код:
str.copy(arrayPtr, min(bytes_to_copy, array_size));

Согласен с постом #6
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #10 : 16-04-2010 18:37 » 

С какой стати они должны по-разному завершаться?

Почему "должны"? Они реально завершаются по-разному. Ты запускал код?

resource, то что ты предлагаешь - попытка исправить кривые ручки. Безопасные ф-ции предназначены совсем для других целей. Представь себе ситуацию, когда ты не в сосотоянии отследить эти параметры. Ну не важно по какой причине (юзвер их ручками кривыми ввёл - он так хотел), но параметры получились неправильные. Это всё работает на одном компе, юзвер хватается за голову, жутко матерится, выдёргивает последние волосинки, но перезапускает прогу и начинает сначала. А в другой ситуации, точно такой же, с небольшим отличием - комп стоит в сети и подвержен всевозможным атакам хакеров. Добавь к этому ещё, например, что прога маслает кучу персональных данных, пароли, номера счетов и тп Те лакомый кусочек для хакеров. Вот тут нерадивые программеры и вспоминают про безопасные ф-ции. Их использование не является обязательным или принудительным, посему и предупреждение, а не ошибка при компиляции, таким образом перекладывая ответственность за последствия на плечи крутых, самонадеянных программеров. "Не далее, не более" (с) Так какие претензии?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 16-04-2010 18:43 » 

С какой стати они должны по-разному завершаться?
Почему "должны"? Они реально завершаются по-разному. Ты запускал код?
Твой код и делает разное:
Цитата
Код:
//nArray = str._Copy_s(arrayPtr, array_size, 50);
nArray = str.copy(arrayPtr, array_size, 50);
Во втором случае 50 - смещение, а не размер. Если убрать этот избыточный параметр, и второй аргумент будет иметь неверное значение, оба кода упадут одинаково.
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 16-04-2010 19:12 » 

Джон, да это не попытка, это просто правильно. Тут слишком много разговоров про кривые руки. Если человек пишет "неправильный" код, то это его проблемы, и тут уже разве что бог ему поможет. Может быть он занят не своим делом.
А про то что ввел юзер, есть такая прописная истина, что всё это надо проверять.
« Последнее редактирование: 16-04-2010 19:16 от resource » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #13 : 20-05-2010 07:09 » 

Еле нашёл тему. Ага Сразу руки не дошли, а потом забывал.

Хочу извиниться.  Краснею Ступил.  Скромно так... Я просто заменил вызов ф-ции без оглядки на смысл параметров. Поэтому у меня всё "работало". При детальном разборе после:

Во втором случае 50 - смещение, а не размер. Если убрать этот избыточный параметр, и второй аргумент будет иметь неверное значение, оба кода упадут одинаково.

понял, что ступил. Сорри. Впредь постараюсь быть внимательней.

Происходит фактически одно и то же, и даже функция в итоге вызывается одна и та же, и в данном случае - с одними и теми же аргументами. Та самая _Copy_s.

Так и есть. Действительно непонятно, зачем они так сделали?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines