NullPointerException
s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException
. Они наиболее распространены, но другие способы перечислены на странице NullPointerException
javadoc.
Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException
, be:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
В первой строке внутри main
я явно устанавливаю ссылку Object
obj
равной null
. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException
, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)
При использовании каких-либо функций обратного вызова с Windows API они должны быть объявлены с помощью CALLBACK
и/или WINAPI
. Это применит соответствующие художественные оформления, чтобы заставить компилятор генерировать код, который чистит стек правильно. Например, на компиляторе Microsoft это добавляет __stdcall
.
Windows всегда использовал __stdcall
соглашение, когда это приводит к (немного) меньшему коду с очисткой, происходящей в вызванной функции, а не на каждом сайте вызова. Это не совместимо с функциями varargs, хотя (потому что только вызывающая сторона знает, сколько аргументов они продвинули).
ESP является указателем вершины стека. Таким образом согласно компилятору, Ваш указатель вершины стека становится испорченным. Трудно сказать, как (или если) это могло бы происходить, не видя некоторый код.
, Каков самый маленький сегмент кода, который можно получить для репродуцирования этого?
Вы получили бы эту ошибку, если функция вызывается с соглашением о вызовах кроме того, это компилируется в.
Visual Studio использует установку соглашения о вызовах по умолчанию, которой это объявляется в опциях проекта. Проверьте, является ли это значение тем же в orignal настройках проекта и в новых библиотеках. По амбициозному dev, возможно, установил это на _stdcall/pascal в оригинале, так как это уменьшает размер кода по сравнению со значением по умолчанию cdecl. Таким образом, базовый процесс использовал бы эту установку, и новые библиотеки получают значение по умолчанию cdecl, который вызывает проблему
, Так как Вы сказали, что не используете специальных соглашений о вызовах, это, кажется, хорошая вероятность.
Также делают разность на заголовках, чтобы видеть, являются ли объявления / файлы, которые видит процесс, теми же, с которыми компилируются библиотеки.
пикосекунда: То, чтобы заставлять предупреждение уйти является BAAAD., который все еще сохраняет базовая ошибка.
у Вас есть какие-либо typedef'd прототипы функции (например, интервал (*fn) (интервал a, интервал b))
, если Вы dom, которым Вы могли бы быть, поняли прототип превратно.
ESP является ошибкой на вызове функции (можно ли сказать который в отладчике?), который имеет несоответствие в параметрах - т.е. стек, восстановил назад к состоянию, которое он запустил в том, когда Вы вызвали функцию.
можно также получить это при загрузке функций C++, которые должны быть объявлены, экстерн C - C использует cdecl, C++ использует stdcall соглашение о вызовах по умолчанию (IIRC). Поместите некоторые обертки экстерна C вокруг импортированных прототипов функции, и можно зафиксировать его.
, Если можно выполнить его в отладчике, Вы будете видеть функцию immediatey. В противном случае можно установить DrWtsn32 для создания мини-дампа, который можно загрузить в windbg для наблюдения стека вызовов во время ошибки (Вам будут нужны символы или mapfile для наблюдения имен функций хотя).
Вы создаете статичный, освобождает или DLLs? Если DLLs, как определенный экспорт; как библиотеки импорта создаются?
прототипы для функций в освобождении точно то же как объявления функции, где функции определяются?
Глушение проверки не является правильным решением. Необходимо выяснить то, что испорчено с соглашениями о вызовах.
существует довольно много способов изменить вызов convetion функции, явно не определяя его. экстерн "C" сделает это, STDMETHODIMP/IFACEMETHODIMP также сделает это, другие макросы могли бы сделать это также.
я верю, если запущено Вашей программе под WinDBG ( http://www.microsoft.com/whdc/devtools/debugging/default.mspx ), время выполнения должно повредиться в точке, где Вы поражаете ту проблему. Можно посмотреть на стек вызовов и фигуру, какая функция имеет проблему, и затем посмотрите на ее определение и объявление, что вызывающая сторона использует.
Другой случай, где esp
может быть испорчен, с непреднамеренным переполнением буфера, обычно посредством ошибочного использования указателей для работы мимо границы массива. Скажите, что у Вас есть некоторая функция C, которая похожа
int a, b[2];
, Запись в b[3]
, вероятно, изменится a
, и где угодно мимо этого, вероятно, польет из шланга сохраненный esp
на стеке.
Я увидел эту ошибку, когда код пытался вызвать функцию для объекта, который не был ожидаемого типа.
Итак, иерархия классов: Родитель с дочерними элементами: Ребенок1 и Ребенок2
Child1* pMyChild = 0;
...
pMyChild = pSomeClass->GetTheObj();// This call actually returned a Child2 object
pMyChild->SomeFunction(); // "...value of ESP..." error occurs here
Эта ошибка отладки означает, что регистр указателя стека не возвращается к своему исходному значению после вызова функции, то есть что количество нажатий перед вызовом функции не было выполнено равным числом всплывающих окон после вызова.
Я знаю 2 причины этого (обе с динамически загружаемыми библиотеками). №1 - это то, что VC ++ описывает в сообщении об ошибке, но я не думаю, что это наиболее частая причина ошибки (см. №2).
1) Несоответствующие соглашения о вызовах:
Вызывающий и вызываемый у вас нет должного соглашения о том, кто что будет делать. Например, если вы вызываете функцию DLL, которая называется _stdcall
, но по какой-то причине она была объявлена в вашем вызове как _cdecl
(по умолчанию в VC ++). Это могло бы случиться, если бы вы вы используете разные языки в разных модулях и т. д.
Вам нужно будет проверить объявление функции-нарушителя и убедиться, что она не объявляется дважды и по-разному.
2) Несовпадающие типы:
Вызывающий и вызываемые объекты не скомпилированы с одинаковыми типами. Например, общий заголовок определяет типы в API и недавно был изменен, и один модуль был перекомпилирован, а другой - нет, т. Е. Некоторые типы могут иметь разный размер в вызывающем и вызываемом.
In В этом случае вызывающий передает аргументы одного размера, но вызываемый (если вы используете _stdcall
, где вызываемый объект очищает стек) выдвигает другой размер. Таким образом, ESP не возвращается к правильному значению.
(Конечно, эти аргументы, а также другие аргументы ниже них, могут показаться искаженными в вызываемой функции,
Я читал это на другом форуме
У меня была та же проблема, но я просто ИСПРАВИЛ ее. Я получал ту же ошибку из следующего кода:
HMODULE hPowerFunctions = LoadLibrary("Powrprof.dll");
typedef bool (*tSetSuspendStateSig)(BOOL, BOOL, BOOL);
tSetSuspendState SetSuspendState = (tSuspendStateSig)GetProcAddress(hPowerfunctions, "SetSuspendState");
result = SetSuspendState(false, false, false); <---- This line was where the error popped up.
После некоторого расследования я изменил одну из строк на:
typedef bool (WINAPI*tSetSuspendStateSig)(BOOL, BOOL, BOOL);
, что решило проблему. Если вы посмотрите в заголовочный файл, в котором находится SetSuspendState (powrprof.h, часть SDK), вы увидите, что прототип функции определен как:
BOOLEAN WINAPI SetSuspendState(BOOLEAN, BOOLEAN, BOOLEAN);
Итак, у вас, ребята, возникла аналогичная проблема. Когда вы вызываете заданную функцию из .dll, ее подпись, вероятно, отключена. (В моем случае это было отсутствующее ключевое слово WINAPI).
Надеюсь, что это поможет любому будущему! : -)
Ура.