Как “оборона” мой код должна быть?

Похоже, вы не понимаете, как объявлять и использовать массив из string и массив указателей на string.

    string part1[ARRAY_SIZE] = { "...", "...", ...

Вы объявляете part1 как массив строк . Но тогда, кажется, есть некоторая путаница в том, как передать этот массив в printpart1(). Вы предоставляете объявление как:

void printpart1(..., string *printpart1[18]) {

Где printpart1 указывает, что параметр printpart1 будет массивом указателей на строку. Затем вы вызываете printpart1() как:

printpart1(ARRAY_SIZE, &part1PTR);

Где вы объявили part1PTR как указатель на строку . Передавая адрес из part1PTR, вы предоставляете printpart1() указатель для указателя на string.

Чтобы получить фактическую строку для печати, сначала необходимо разыменовать printpart1 (например, *printpart1), чтобы получить указатель на строку перед применением любого смещения и разыменования, например, *(*printpart1 + i).

Например, следующее обеспечит желаемый вывод строки:

void printpart1(int length, string *printpart1[18]) {
    int dummy;
    for (int i = 0; i < length; i++)
        cout << *(*printpart1 + i) << endl;

    cin >> dummy;

}

(примечание : *(*printpart1 + 1) эквивалентно (*printpart1)[i]. Все, что имеет больше смысла) Вам обычно используется вторая форма)

Просто передайте массив

Теперь все это чрезмерно усложняет то, что должно быть так просто, как передача самого массива в printpart1(), например если вы измените свою функцию на:

void printpart1(int length, string *printpart1) {
    int dummy;
    for (int i = 0; i < length; i++)
        cout << printpart1[i] << endl;

    cin >> dummy;
}

Вы больше не нуждаетесь в part1PTR и можете просто вызвать вашу функцию с помощью:

    printpart1 (ARRAY_SIZE, part1);

Посмотрите вещи, продумайте их и позвольте мне знать, если у вас есть дополнительные вопросы.

12
задан JaredPar 15 May 2009 в 16:17
поделиться

15 ответов

Я не знаю, есть ли какой-нибудь способ ответить на этот вопрос. Это просто то, чему вы научитесь на собственном опыте. Вам просто нужно спросить себя, насколько распространенной может быть потенциальная проблема, и высказать свое мнение. Также учтите, что у вас не обязательно есть , чтобы всегда писать защитный код. Иногда допустимо просто отметить любые потенциальные проблемы в документации по вашему коду.

В конечном счете, я думаю, что это просто то, в чем человек должен следовать своей интуиции. Нет правильного или неправильного способа сделать это.

4
ответ дан 2 December 2019 в 03:32
поделиться

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

14
ответ дан 2 December 2019 в 03:32
поделиться

Я склонен изменять степень защиты, которую я устанавливаю в свой код, в зависимости от языка. Сегодня я в основном работаю на C ++, поэтому мои мысли двигаются в этом направлении.

При работе на C ++ не может быть достаточно защитного программирования. Я отношусь к своему коду так, как будто я охраняю ядерные секреты, и все остальные программисты стремятся их получить. Утверждения, выбросы, взлом шаблонов ошибок времени компилятора, проверка аргументов, устранение указателей, углубленный анализ кода и общая паранойя - все это честная игра. C ++ - злой чудесный язык, который я люблю и очень не доверяю.

10
ответ дан 2 December 2019 в 03:32
поделиться

Я не поклонник термина «защитное программирование». Мне он предлагает такой код:

void MakePayment( Account * a, const Payment * p ) {
    if ( a == 0 || p == 0 ) {
       return;
    }
    // payment logic here
}

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

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

Изменить: Я не согласен с некоторыми другими ответами и комментариями здесь - я согласен не думайте, что все функции должны проверять свои параметры (для многих функций это просто невозможно). Вместо этого я считаю, что все функции должны документировать приемлемые значения и указывать, что другие значения приведут к неопределенному поведению.

9
ответ дан 2 December 2019 в 03:32
поделиться

Если вы работаете над общедоступными API-интерфейсами компонента, то стоит провести тщательную проверку параметров. Это привело меня к привычке проводить валидацию везде. Это ошибка. Весь этот код проверки никогда не тестируется и потенциально делает систему более сложной, чем она должна быть.

Теперь я предпочитаю проверять с помощью модульного тестирования.

2
ответ дан 2 December 2019 в 03:32
поделиться

Я всегда отлаживаю. Подтверждаю свои предположения.

1
ответ дан 2 December 2019 в 03:32
поделиться

Моя личная идеология: защищенность программы должна быть пропорциональна максимальной наивности / незнанию потенциальных пользователей.

1
ответ дан 2 December 2019 в 03:32
поделиться

Защита от разработчиков, использующих ваш код API, ничем не отличается от защиты от обычных пользователей.

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

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

1
ответ дан 2 December 2019 в 03:32
поделиться

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

Если у вас есть тесты, и какой-то другой разработчик пытается уничтожить ваш код, тесты не пройдут . Но опять же, это зависит от тестового покрытия вашего кода (если оно есть).

0
ответ дан 2 December 2019 в 03:32
поделиться

Защитное программирование - это только один из способов составления контракта с помощью разработки по контракту способа кодирования.

Два других способа

  • полное программирование и
  • номинальное программирование.

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

//precondition : par is so and so and so 
function doSth(par) 
{
debug.assert(par is so and so and so )
//dostuf with par 
return result
}
0
ответ дан 2 December 2019 в 03:32
поделиться

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

Когда у вас есть такой образ мышления, ключ к тому, чтобы быть последовательным в своем подходе. вы ожидаете вернуть коды состояния, чтобы сообщить о проблемах в цепочке вызовов, или вам нравятся исключения. смешанные модели убьют вас или, по крайней мере, заставят выпить. сильно. если вы используете чужой API, затем изолируйте эти вещи в механизмы, которые ловят / сообщают в терминах, которые вы используете. используйте эти интерфейсы упаковки.

0
ответ дан 2 December 2019 в 03:32
поделиться

Системы должны иметь хорошо спроектированные границы, в которых происходит защитная проверка. Должно быть решение о том, где пользовательский ввод проверяется (на какой границе) и где другие потенциальные защитные проблемы требуют проверки (например, сторонние точки интеграции, общедоступные API-интерфейсы, взаимодействие с системой правил или разные блоки, написанные разными командами программистов. ). Более защитная проверка, чем это, во многих случаях нарушает DRY и просто увеличивает стоимость обслуживания с очень небольшой выгодой.

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

0
ответ дан 2 December 2019 в 03:32
поделиться

Недавно у меня был сценарий, в котором данные, вводимые пользователем, распространялись через интерфейс удаленного фасада, затем через локальный интерфейс фасада, затем через какой-то другой класс, чтобы наконец добраться до метода, в котором они фактически использовались. Я задавал себе вопрос: Когда должно быть проверено значение? Я добавил код проверки только в последний класс, где фактически использовалось значение. Добавление других фрагментов кода проверки в классы, лежащие на пути распространения, было бы для меня слишком защитным программированием. Единственным исключением может быть удаленный фасад, но я его тоже пропустил.

0
ответ дан 2 December 2019 в 03:32
поделиться

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

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

Кодирование с защитой от другого кода, такого как ваша платформа или другие модули, - это то же самое, что и пользователи: они хотят вас достать. ОС всегда будет менять ваш поток в неподходящее время, сети всегда уходят в неподходящее время, и в целом зло изобилует за каждым углом. Вам не нужно кодировать каждую потенциальную проблему - затраты на обслуживание могут не окупать повышения безопасности - но думать об этом не повредит. И обычно это не так

0
ответ дан 2 December 2019 в 03:32
поделиться

Хороший вопрос, я колебался между проверкой работоспособности и отказом от нее. Это ситуация 50/50

, я бы, вероятно, выбрал золотую середину, где я бы только "Bullet Proof" любые подпрограммы, которые:

(a) Вызываются из более чем одного места в проекте

( b) имеет логику, которая ВЕРОЯТНО изменится

(c) Вы не можете использовать значения по умолчанию

(d) процедура не может быть корректно «неудачна»

Darknight

0
ответ дан 2 December 2019 в 03:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: