Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. Я вспоминаю этот взлом, как записанный Bob Smith, который сделал старого диспетчера памяти эры DOS, названного 386MAX (или "386 Max"). Это не была часть продукта, это было немного утилиты, которую он сделал на скорую руку и отправил где-нибудь. Однако в сети единственная ссылка на эту технику, которую я могу найти, столбец DDJ Undocumented Corner от ноябрь 1996 Robert Collins.
До Intel, представляющего инструкция CPUID , было трудно проверить точный тип и уровни пересмотра ЦП в Вашей системе. Оказывается, что в большинстве версий 386 и позже, на самом деле было идентификатором ЦП, но это было только видимо в одно определенное время: прямо после того, как процессор был сброшен в регистре EDX. (Предполагалось, что BIOS компьютера будет единственным программным обеспечением, законно заинтересованным этим).
проблема: как нормальная программа может получить это значение регистра, если мы не BIOS?
Этот взлом полагался на шесть отличных особенностей IBM PC совместимые компьютеры. Они были следующие:
программа объединила знание всех этих частей мелочей для достижения цели.
результатом была программа строки команды DOS, которая сделала следующее:
, Когда "мягкая" перезагрузка произошла, процессор попытается перейти к вершине вывода данных 16 байтов, который является, где код запуска ROM расположен. Однако, так как A20 был выключен, он на самом деле перейдет к вершине вывода данных 16 байтов минус один мегабайт . На большинстве ПК там нет никакой RAM. Таким образом, это выбрало бы ряд 0xFF байтов от этой несуществующей RAM и попыталось бы выполнить его. Это создало бы недопустимое исключение кода операции.
Его обработчик исключений тогда щипнул бы значение EDX (CPUID) и спрятал бы его где-нибудь, он мог найти его. Это тогда разгребло бы бардак (снова включите A20, зеркальное отражение назад от защищенного режима до реального режима для DOS), и управление возвратом к исходному коду.
, Когда это работало, это был гений для созерцания. Вуаля, здесь была простая DOS-программа командной строки, которая даст Вам значение CPUID.
, Конечно, были неизбежно ПК там, которые были "не совсем совместимы", который откажет ужасно, когда Вы выполнили это. А-ч хорошо.
quake3 обратный квадратный корень и переключатель Волшебства Волшебства/Больше MIT обычно входят в эти списки.
Ну, это не является самым прохладным, но это определенно забавно (программистам).
Мы создали разработчика специального запроса для проекта базы данных резюме. Были некоторые ajaxy части к нему, и основная идея состояла в том, что, если Вы изменились что-нибудь на странице, поиск автоматически повторно выполнил себя. (Это было инициировано onBlur событием всех виджетов UI)
, Таким образом, у нас не было реального использования для кнопки "Search" или "Run Query". Это смутило пользователей ни к какому концу. Таким образом, мы добавили кнопку поиска, которая ничего не сделала. Это просто находилось там.
Это работало, потому что каждый раз Вы нажали кнопку поиска, onBlur событие от поля, на котором Вы были только, будет стрелять.
Это сделало нашу базу пользователей очень счастливой. Простые вещи.
Это не было взломом, который я сделал, а скорее кто-то, кого я работал, в течение долгого времени назад сказал мне об этом (он на самом деле сделал взлом).
кажется, что он работал на кого-то, кто был слепым и кому был нужен способ считать текстовые файлы. Таким образом, он выяснил, как перевести текстовые файлы в шрифт Брайля и распечатать их использование различных символов такой как. и:
принтеры в то время были контактными принтерами, поэтому когда символ был распечатан, механизм печати ударил бумагу достаточно трудно для отъезда впечатления, которое можно было чувствовать. Начиная с впечатления, сформированного в конце бумаги, он должен был распечатать инвертированный назад шрифт Брайля так, чтобы, когда бумага была изменена к лучшему, это было корректно.
, Конечно, действие чтения уничтожило депрессии, таким образом, это было чтение однажды механизм, но я всегда думал, что это было довольно прохладным взломом.
При работе над усилием инженерного анализа iPhone я нашел уязвимость в основной полосе (микросхема, которая обрабатывает телефонию и блокировку поставщика услуг), который позволил бы Вам писать нули произвольно. Хотя это казалось бесполезным сначала, быстро стало очевидно, что это могло сделать намного больше, чем я первоначально думал. С путем работает ARM, определенные переходы могли быть сделаны аннулированными пишущий единственный нуль в цели, заставляя путь выполнения всегда продолжиться вперед. Это включило программное обеспечение, разблокировали, но был быстро заменен более устойчивым взломом, который позволил Вам повторно высвечивать основную полосу полностью.
Все еще чертовски гордящийся тем взломом, независимо от его бесполезности теперь.
Я сделал счетчик divide-eight из пневматических клапанов в колледже, чтобы быть освобожденным от остатка от курса пневматики.
Его такая тривиальная вещь, но когда я увидел этот код в первый раз (таким же моим разработчиком) я был потрясен, потому что это - что-то, что я имел бы никогда мысль (комментарии добавленный мной):
cglobal x264_sub8x8_dct_sse2, 3,3 ;3,3 means 3 arguments and 3 registers used
.skip_prologue:
call .8x4
add r0, 64 ;increment pointers
add r1, 4*FENC_STRIDE
add r2, 4*FDEC_STRIDE
.8x4:
SUB_DCT4 2x4x4W ;this macro does the actual transform
movhps [r0+32], m0 ;store second half of output data
movhps [r0+40], m1 ;the rest is done in the macro
movhps [r0+48], m2
movhps [r0+56], m3
ret
Это делает 8x8, блок 4 преобразовывает путем выполнения наборов 8x4 за один раз. Но это не вставляет код дважды (который потратил бы впустую размер кода), и при этом это не имеет 8x4 функция и называет его дважды. И при этом это не имеет цикла также. Вместо этого это вызывает "функцию" и затем увеличивает указатели, и затем "падает" прямо в него и делает это снова.
Это получает лучший из обоих миров: никакой вызов функции наверху вне оригинала (так как указатели r0, r1, и r2 не увеличены в SUB_DCT4) и никакое дублирование кода, и никакой цикл наверху.
Этим летом я записал игру, что я называю SatelliteRush. Это - Разъединительная игра для мобильных телефонов с Java и GPS. Это может играться в двух режимах: "скучный режим" и "спутниковый режим". В скучном режиме Вы используете кнопки для перемещения весла, столь же обычного, но в спутниковом режиме это использует GPS-приемник телефона. Вы работаете назад и вперед, и перемещения весла с Вами.
я только протестировал его на Sony-Ericsson W760i, и это работает обоснованно хорошо, учитывая, что обновления положения GPS являются довольно медленными и неточными.
До сих пор я сделал "техническую тестовую версию" этой игры, таким образом, это, не очень красиво или прост в использовании. Но если у Вас есть телефон GPS с Java, можно загрузить его здесь: http://www.lysator.liu.se/~padrone/temporary/SatelliteRushTest/
РЕДАКТИРОВАНИЕ:
Теперь доступный для Android как бесплатное приложение на Android Market: https://market.android.com/details? id=se.nekotronic.satelliterush
Устройство Вареного пудинга . Проводит тот подсчет?:)
Устройство Вареных пудингов , для вышеупомянутого вопроса.
История Mel. Жесткий взлом.
Я получил ранний компьютер Commodore 64 и должен был записать ассемблерный код для него.
проблема была, не было никакой Ассемблерной Программы для C64 (или что, или я не мог позволить себе один).
, Таким образом, я записал ассемблер путем поиска этих 6 502 кодов операций в книге и создания программы из необработанных байтов.
В какой-то момент это смогло взять ассемблерный код в качестве своего входа и собраться в программу.
мой друг А записал дизассемблер для своего ДОМАШНЕГО ЖИВОТНОГО в ОСНОВНОМ. Я использовал эту программу для разборки моего ассемблера и затем смог использовать свой ассемблер для сборки более новых версий себя.
, О, обручи мы должны были перейти через за былые времена :)
Самый прохладный взлом (и это не действительно взлом в истинном значении слова, но это передает, а также некоторые вышеупомянутые ответы), я когда-либо создавал, был на моей Apple//e.
была одна строка в справочнике, в котором было сказано, что $C010 был 'любым ключом вниз' флаг.
то, Которым это оказалось, было верно. Высокий бит программного коммутатора $C010 сказал бы Вам, если бы ключ снизился или не несмотря на встроенные ключевые повторные аппаратные средства.
, Что они не сказали Вам и все узнали, что твердый путь состоял в том, что был не надежно способ узнать, КАКАЯ клавиша нажималась.
, Если Вы записали немного программы сборки... (прощают мои ошибки, мои 6 502 блока много ржавы)
:1
lda $C010
cmp #$80
bcc :1 ; branch if less than? I forget how to do that.
lda $C000
jsr $FDF0 ;output the accumulator value to the screen
, Таким образом, это циклично выполнилось бы, пока Вы не нажали клавишу и произведете ключ путем загрузки от переключателя чтения клавиатуры $C000.
, Но если бы Вы запустили ту программу, она не вполне работала бы правильно.
Это, конечно, распечатало бы что-то при удержании ключа и ничего, когда Вы не были слишком было немного задержки на шине где-нибудь (я думаю, я не аппаратный парень), поэтому, если бы Вы нажали 'f', то Вы получили бы много f's. Но если бы Вы остановили, затем нажали 'g', то Вы получили бы набор 'f's, прежде чем он переключился на 'g'.
Вы видели доказательство этой проблемы в яблоке] [версия Рукавицы, Вы переместитесь в одно направление, и если бы Вы пытались переместиться во второе направление, то Вы переместились бы немного в свое первоначальное направление, пока Вы не передали задержку.
Это не имело никакого смысла действительно, потому что показания $C000 были всегда на 100% точны, если Вы не проверили с помощью ping-запросов $C010 сначала.
я нашел эту проблему захватывающей и после недель проигрывания, я наконец придумал то, что я все еще думаю, самая прохладная программа, которую я когда-либо писал.
сама программа не имела никакого смысла, она сделала несколько бесполезных РТОВ, но по некоторым причинам она работала, и она привела к правильным значениям от $C000 после запросов $C010.
Настолько прохладный было это, я написал статью для журнала откусывания, который они приняли, но никогда не публиковали (или потому что они обанкротились или потому что чтение статьи как он было записано на 15 лет, которыми это было), где я записал заменяющую программу ввода с клавиатуры и сцепил ее в нулевое местоположение страницы, которое все называют для получения ввода с клавиатуры, и я смог программно изменить задержку повторения клавиатуры и повторный уровень, что-то, что было в других отношениях невозможно, поскольку он был соединен проводом в аппаратные средства. Конечно, Apple//e продвигалась в той точке, но все еще по сей день, мой самый прохладный взлом.
Обновление 02.03.2010: Проходя некоторые старые бумаги, я нашел распечатку своей небольшой ассемблерной подпрограммы. Я отправляю его здесь, чтобы видеть, может ли кто-либо выяснить, почему это работает, и таким образом, это будет навсегда храниться в цифровой форме где-нибудь...
$0300 AD 10 C0 LDA $C010 ; load accumulator with any-key-down flag
$0303 29 80 AND #$80 ; keep only high bit flag
$0305 0D 00 C0 ORA $C000 ; OR accumulate with keyboard soft switch
$0308 10 F9 BPL $0303 ; erm, I forget exactly which branch this is
$030A 09 80 ORA #$80 ; turn the high bit on
$030C 20 ED FD JSR $FDED ; print char in accumulator
$030F 4C 00 30 JMP $0300 ; start again.
Не Имеет никакого смысла, почему это должно работать, но это делает. Или сделал. 25 лет назад.
Быстрый Обратный Квадратный корень - причудливая небольшая стандартная программа, которой так или иначе удается вычислить обратный квадратный корень чего-то, но Вы никогда не предполагали бы это от рассмотрения его.
http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/
Мой друг заменял материнскую плату в своей Dell с более новым, быстрее, материнскую плату OEM. Однако он не мог получить кнопку питания и другой материал на передней панели, для работы - коннекторы были различными размерами с различными разметками контакта. Я взял набор запасных перемычек и запасных проводов, и соединил надлежащие контакты один за другим. Ни для какого запаивания не было нужно:)
мудрый Кодом, я постоянно впечатляюсь. Я всегда думал, что не было никакого изящного способа определить, является ли fork
ребенок редактора успешно exec
редактор, но там на самом деле .
ребенок:
execvp(argv[0], argv);
errval = errno;
write(data->fd, &errval, sizeof(errval));
родитель:
socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
flag = fcntl(fds[1], F_GETFD) | FD_CLOEXEC;
fcntl(fds[1], F_SETFD, flag);
pid = clone(child, NULL, SIGCHLD, NULL);
if(pid < 0){
...
}
close(fds[1]);
/* Read the errno value from the child, if the exec failed, or get 0 if
* the exec succeeded because the pipe fd was set as close-on-exec.
*/
n = read(fds[0], &ret, sizeof(ret));
if (n < 0) {
...
} else if(n != 0){
/* exec failed */
} else {
/* exec succeeded */
}
После нескольких дней отладки сервера коммутируемого доступа, который испытывал недопустимое количество потерянных вызовов, я проследил проблему до механизма аутентификации собственной разработки, который зависел от текстового представления выполнения getty
PID. Эти getty
генерировал бы ошибку и аварийное прекращение работы, если бы его PID содержал четное число, сопровождаемое 9, заставляя вызов отбросить и getty
, чтобы повторно метать икру с новым PID.
После того, как проблема была определена, я был взят от проекта и позже обнаружил, что "фиксация" должна была изменить числовое к тексту преобразование от
sprintf(strval, "%d", pid);
к
sprintf(strval, "%o", pid);
Вместо того, чтобы диагностировать стандартную программу аутентификации, кто-то принял решение преобразовать PID в восьмеричный , лишив возможности содержать 9!
И программа самопечати ('Куайн') в C#, 149 символов в длину:
class P{static void Main(){var S=“class P{{static void Main(){{var S={1}{0}{1};System.Console.Write(S,S,’{1}’);}}}}”;System.Console.Write(S,S,‘”‘);}}
Пара несколько лет назад я разрабатывал веб-интерфейс и использовал некоторый совершенно новый JS, освобождает для функциональности Ajax. Lib только eval'd JS, который был в заголовке документа HTML, но был слишком большим количеством данных, возвращаемых для вписываний в заголовок. Что сделать?
Некоторый ввод по абсолютному адресу вокруг показанного, что JS в заголовке имел доступ к телу документа HTML, таким образом, я записал универсальной 'оценке тело' функция, которая была возвращена в заголовке. Очень полезный в то время, особенно b/c различный lib JS мы оценивали только eval'd JS от тела, таким образом, это было совместимо и для JS, освобождает и избежал любых ограничений размера от заголовка!
Да, простой, но я чувствовал себя довольно удивительным в течение целого месяца после понимания этого:)
Наблюдение моего бывшего коллеги, переписывающего PlayStation один 3-й механизм в течение трех недель с нуля в ассемблере. Старый должен был замедлиться, и мы не сделали имел время для изменения графических активов больше. Он запустил ту перезапись, двухмесячную перед крайним сроком.
Это был тот же парень (и некоторые другие чуваки также - это было действие работы в команде), кто сделал удивительное задание, наполняющее 10 минут графики и звука в исполняемый файл 64 КБ.
При взгляде на то, как использовать TCP в 4D, я столкнулся с этим изменением Устройства Вареного пудинга в документации:
$SentOK:=False //A flag to indicate if we made it through all of the calls
Case of
: (SMTP_New ($smtp_id)!=0)
: (SMTP_Host ($smtp_id;<>pref_Server)!=0)
: (SMTP_From ($smtp_id;vFrom)!=0)
: (SMTP_To ($smtp_id;vTo)!=0)
: (SMTP_Subject ($smtp_id;vSubject)!=0)
: (SMTP_Body ($smtp_id;vMessage)!=0)
: (SMTP_Send ($smtp_id)!=0)
Else
$SentOK:=True //message was composed and mailed successfully
End case
If ($smtp_id!=0) //If a Message Envelope was created we should clear it now
$OK:=SMTP_Clear ($smtp_id)
End if
я посмотрел на него и думал, что это было действительно умно (я все еще делаю). К сожалению, это не было тем, в чем я нуждался, и я никогда не получал шанс использовать его.
Не мной:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
int i;
printf("((((");
for(i=1;i!=argc;i++){
if( strcmp(argv[i], "^")==0) printf(")^(");
else if(strcmp(argv[i], "*")==0) printf("))*((");
else if(strcmp(argv[i], "/")==0) printf("))/((");
else if(strcmp(argv[i], "+")==0) printf(")))+(((");
else if(strcmp(argv[i], "-")==0) printf(")))-(((");
else printf("%s", argv[i]);
}
printf("))))\n");
return 0;
}
Если Вы хотите много кода C с невероятными взломами, попробуйте Международный Запутываемый Конкурс Кода C . Они обычно - не виды вещей, которые Вы хотите быть пойманными, делая, но они являются впечатляющими так или иначе.
В первый раз я должен был попытаться понять и изменить часть кода, написанного в функциональном стиле. Я провел час, пытаясь понять, где что-либо произошло, затем нашло, что вся работа была сделана в строке, которая выглядела примерно так:
for my $row (@data) {
push @formatted, join ",", map $format[$_]->($data->[$_]), 0..$#$data;
}
Я разыскал автора и воскликнул, "Почему Вы не прокомментировали это???" Его ответ был, "Чему поможет комментарий?" Я пытался думать один, и отказавший.
Тот код учил мне технику, что я нашел очень полезными по сей день. Однако я узнал, что это - техника, которая должна использоваться часто или никогда, но нигде не промежуточный. Поскольку, действительно, никакой комментарий не поможет. Или Вы понимаете, что существует строка там, что это делает, и что Вы не должны волноваться об этом, или иначе Вы не поймете тот код.
Тот же программист обычно делал другие впечатляющие вещи. Например, в предыдущем задании он изменил библиотеку C так, чтобы, когда программа C вывела ядро, это только вывело ядро. Вместо этого это создало бы coredump, затем послало бы электронное письмо группе разработчиков со следом стека и присоединенным coredump. Это позволило им замечать и исправлять ошибки в заданиях крона, которые имели проблемы.
Я записал ассемблер для маленькой Виртуальной машины (UDVM) с Excel и Visual Basic. Вы пишете свой ассемблерный код в ячейках Excel и свое расположение памяти в другом рабочем листе, и затем в нижней части двоичные строки машинного кода будут вычислены. Вообразите страх руки assemblying каждым разом, когда Вы изменяете свой ассемблерный код.
Кастинг строки с.ToString () всегда является WTF, который я нахожу.
Назад в средней школе я действительно гордился записью 3-й программы построения графика на моем ti-83, потому что мои родители не купят меня 89.
Создание сканера из печатающей головки. Современные версии включают Canon , но этот прием на самом деле действительно стар.
Существует переключатель, вложенный в цикле для раскручивания цикла, известного как устройство Вареного пудинга
dsend(to, from, count)
char *to, *from;
int count;
{
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}
не НАСТОЛЬКО мощный однако, это - хорошее злоупотребление синтаксисом C
http://pida.co.uk/ взлом А, который закончил бы войну пламени Vim/Emacs! (!! 11eleven)
Загрузчик для ЦП, который не поддерживал загрузчики.
ЦП является derivitive члена rockwell семьи CPU, которая выполняет код, который он дан. Набор инструментальных средств производит любую RAM изображения (в котором Вы можете JTAG и работать за отладкой), ИЛИ это производит образы ROM.
существует загрузчик объединения в цепочку. Но это только цепочки. Необходимо работать, и это только работает на RAM.
На всякий случай я чувствовал себя творческим, ЦП не имеет никакой инструкции JMP. (Я не шучу.) Никакая инструкция RST также.
, Таким образом, мы должны были загрузить программу из файловой системы и выполнить ее, и этот ЦП очень определенно встраивается и не хочет делать это.
файловая система находилась во Флэш-ROM и будет только работать в адресе, в котором она была записана. (Это не перемещаемо)
, Таким образом, я загрузил ROM загрузчиком, который загрузится, загружают загрузчик в нижнюю часть RAM. ЦП пишет в вентильную матрицу, что
1) утверждает сброс. 2) подкачивает сигналы выбора кристалла для RAM, и ROM 3) выпускает сброс.
ЦП заканчивает тем, что работал от RAM, готовой прочитать код от файловой системы в RAM.
Это на самом деле работает. Я был "вдохновлен" по тому, как IBM PC AT вытаскивает 286 микросхем из защищенного режима.