Используя эту функцию PHP mysql_escape_string()
, вы можете быстро получить хорошую профилактику.
Например:
SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."'
mysql_escape_string
- Сбрасывает строку для использования в mysql_query
Для большей профилактики вы можете добавить в конце ...
wHERE 1=1 or LIMIT 1
Наконец вы получаете:
SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."' LIMIT 1
Разыменование, когда переведено в машинный код, может означать разные вещи в зависимости от того, что Вы делаете с разыменованным объектом. Доступ к единственному члену класса через указатель является обычно дешевым. Например, если c является указателем на экземпляр class C
с int
участник n тогда что-то вроде этого:
int n = c->n;
Мог бы перевести в одну или две машинных команды и мог бы загрузить регистр единственным доступом к памяти.
, С другой стороны, это подразумевает создание полной копии объекта, на который указывает c:
C d = *c;
стоимость этого будет зависеть от размера C, но отмечать, что это - копия, которая является крупным расходом, и 'разыменовать' часть действительно просто 'использует' адрес указателя в инструкциях по копии.
Примечание, что доступ к членам больших объектов обычно требует вычисления смещения указателя и доступа к памяти, является ли объект локальным объектом или нет. Обычно только очень маленькие объекты оптимизированы для проживания только в регистрах.
, Если Вы обеспокоены стоимостью указателей по ссылкам тогда, не. Различием между ними является различие в языковой семантике и к тому времени, когда машинный код является сгенерированным указателем и ссылочным взглядом доступа точно то же.
Наиболее важный фактор в разыменовании указателей в обычных системах - то, что Вы, вероятно, генерируете неудачное обращение в кэш. Произвольный доступ в памяти SDRAM стоит десятков наносекунд (например, 64). На gigaherz процессорах это означает, что Ваш процессор бездействует сотни (или> тысяча) циклов, не имея возможности из выполнения чего-либо еще тем временем.
Только на SRAM основывал системы (который Вы только найдете во встроенном программном обеспечении), или когда Ваше программное обеспечение будет оптимизированным кэшем, факторы, обсужденные в других сообщениях, играют роль.
Разыменование может быть дорогим главным образом, потому что оно стоит инструкции выбрать данные из памяти, которые могли бы быть далеко и не показывают местность ссылки. В этом случае процессор должен выбрать данные из некэшируемой памяти и даже жесткого диска (в случае трудного отсутствия страницы).
Разыменование (нескольких) циклы ЦП стоимости.
Вместо записи:
string name = first->next->next->next->name;
int age = first->next->next->next->age;
this is O(n)
Запись это как:
node* billy_block = first->next->next->next;
string name = billy_block->name;
int age = billy_block->age;
this is O(1)
, Таким образом, Ваш код не "спросит" каждый блок только для получения до четвертого блока.
Несколько разыменование похоже на наличие окружения, кто только знает соседа рядом с ними.
Воображают, спрашиваете ли Вы человека от первого блока, где делает Вашего друга Billy, находится, он скажет Вам, что не знает Вашего друга, он скажет Вам, что только знает соседа рядом с ними, тогда он просто скажет Вам спрашивать своего соседа, тогда Вы спросите его соседа, он ответит на то же самое, как первый блок сделал, Вы продолжаете спрашивать, пока Вы не прибываете в блок своего друга. Не очень эффективный
Разыменование указателя не должно намного больше, чем копировать адрес в (адрес) регистр. Это - все.
Это зависит от того, что Вы делаете с разыменованным указателем. Простое разыменовывает операцию, ничего не делает сам по себе. Это просто получает lvalue типа T
который представляет Ваш объект, если Ваш указатель является a T*
struct a {
int big[42];
};
void f(a * t) {
// does nothing. Only interesting for standard or compiler writers.
// it just binds the lvalue to a reference t1.
a & t1 = *t;
}
Если Вы на самом деле вытаскиваете значение из того объекта, обозначенного lvalue, возвращенным разыменовать операцией, компилятор должен скопировать данные, которые содержит объект. Для простого POD, который является просто простым memcpy
:
a aGlobalA;
void f(a * t) {
// gets the value of of the object denoted by *t, copying it into aGlobalA
aGlobalA = *t;
}
Мои gcc выходы порта этот код для f:
sub $29, $29, 24 ; subtract stack-pointer, creating this frame
stw $31, $29, 20 ; save return address
add $5, $0, $4 ; copy pointer t into $5 (src)
add $4, $0, aGlobalA ; load address of aGlobalA into $4 (dst)
add $6, $0, 168 ; put size (168 bytes) as 3rd argument
jal memcpy ; call memcpy
ldw $31, $29, 20 ; restore return address
add $29, $29, 24 ; add stack-pointer, destroying this frame
jr $31
Оптимизированный машинный код использовал бы встроенный код вместо вызова к memcpy
, но это - действительно просто деталь реализации. То, что важно, настолько просто *t
не выполняет кода, но получает доступ к значению того объекта, на самом деле должен скопировать его.
Был бы мы иметь отношение к типу, имеющему определяемый пользователем оператор присваивания копии, дела более сложны:
struct a {
int big[42];
void operator=(a const&) { }
};
Код для той же функции f
теперь похож:
sub $29, $29, 8
add $29, $29, 8
jr $31
Ха. Но это не было такое удивление, не так ли? В конце концов, компилятор, как предполагается, называет наш operator=
, и если это ничего не делает, целая функция также ничего не делает!
Я думаю вывод, который мы можем сделать, все это зависит от как возвращенное значение operator*
используется. Если у нас есть просто указатель, который мы разыменовываем, мы видим, выше которого код, сгенерированный в основном, зависит от обстоятельств. Я не имею, показал, как это ведет себя, если мы разыменовываем тип класса, перегружавшийся operator*
. Но по существу, это просто ведет себя как, мы видели с operator=
. Все измерения были, покончили -O2
, таким образом, компилятор правильно встроил вызовы :)