Как дорогой это должно разыменовать указатель?

Используя эту функцию 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
44
задан Rakete1111 4 September 2016 в 19:47
поделиться

6 ответов

Разыменование, когда переведено в машинный код, может означать разные вещи в зависимости от того, что Вы делаете с разыменованным объектом. Доступ к единственному члену класса через указатель является обычно дешевым. Например, если c является указателем на экземпляр class C с int участник n тогда что-то вроде этого:

int n = c->n;

Мог бы перевести в одну или две машинных команды и мог бы загрузить регистр единственным доступом к памяти.

, С другой стороны, это подразумевает создание полной копии объекта, на который указывает c:

C d = *c;

стоимость этого будет зависеть от размера C, но отмечать, что это - копия, которая является крупным расходом, и 'разыменовать' часть действительно просто 'использует' адрес указателя в инструкциях по копии.

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

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

70
ответ дан CB Bailey 26 November 2019 в 21:40
поделиться

Наиболее важный фактор в разыменовании указателей в обычных системах - то, что Вы, вероятно, генерируете неудачное обращение в кэш. Произвольный доступ в памяти SDRAM стоит десятков наносекунд (например, 64). На gigaherz процессорах это означает, что Ваш процессор бездействует сотни (или> тысяча) циклов, не имея возможности из выполнения чего-либо еще тем временем.

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

17
ответ дан user52875 26 November 2019 в 21:40
поделиться

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

8
ответ дан Mehrdad Afshari 26 November 2019 в 21:40
поделиться

Разыменование (нескольких) циклы ЦП стоимости.

Вместо записи:

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, находится, он скажет Вам, что не знает Вашего друга, он скажет Вам, что только знает соседа рядом с ними, тогда он просто скажет Вам спрашивать своего соседа, тогда Вы спросите его соседа, он ответит на то же самое, как первый блок сделал, Вы продолжаете спрашивать, пока Вы не прибываете в блок своего друга. Не очень эффективный

5
ответ дан Michael Buen 26 November 2019 в 21:40
поделиться

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

0
ответ дан EricSchaefer 26 November 2019 в 21:40
поделиться

Это зависит от того, что Вы делаете с разыменованным указателем. Простое разыменовывает операцию, ничего не делает сам по себе. Это просто получает 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, таким образом, компилятор правильно встроил вызовы :)

42
ответ дан Lii 26 November 2019 в 21:40
поделиться
Другие вопросы по тегам:

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