Первое, что нужно сказать: я программирую на относительно неизвестном языке: Blitzmax, который является объектно-ориентированным базовым диалектом.Почему мой объект становится NULL с одной строки на другую? - Может быть, это аппаратная штука?
Моя проблема заключается в следующем: Я написал debugmanager, который работает в своем потоке. Поэтому из каждой позиции в программе (это будет игра) вы можете добавить debug- или errormessages в очередь менеджера. В своем потоке он будет извлекать сообщения из очереди и обрабатывать их, записывая их в файл и (если в сообщении есть текущие выбранные Debuglevel, Debugcategory и outputcategory, которые являются только перечислениями), напишите его на консоль.
Теперь я тестировал программу на трех системах: мой настольный ПК с ОС Windows 8 в качестве ОС, мой собственный ноутбук с Windows 7 и ноутбук друга, который также имеет окна 7. На моем компьютере и ноутбуке моего друга Все отлично. Но на моем собственном ноутбуке я почти каждый раз получаю сообщение об ошибке «EXCEPTION_ACCESS_VIOLATION», когда менеджер обрабатывает сообщения. Иногда программа работает нормально, но большую часть времени она ломается с этой ошибкой. Даже в debugmode не отображается строка или stacktrace, что очень затрудняет ее отладку.
Я сломал все необходимые классы до минимума атрибутов и функциональности, чтобы облегчить поиск проблемы. Теперь очередь - это просто список (который изначально встроен в Blitzmax), и сообщение имеет только один атрибут, который является строкой. Также debugmanager только записывает сообщение в консоль, не передавая его методу процесса, который записывает его в файл и т. Д.
Таким образом, действительно нужен код.
Это сообщение:
Type TThreadsafeMessage
Field complete_String:String
Method New_ThreadsafeMessage:TThreadsafeMessage(actual_Message:String, from_File:String, debugCategory:TDebugCategory_Enum, ..
debugLevel:TDebugLevel_Enum, outputCategory:TOutputCategory_Enum, from_Class:String = "", from_Method:String = "")
'Just create the string from the parameters.
Self.complete_String = actual_Message + " | " + from_File + "/" + from_Class + "/" + from_Method
Return Self
End Method
Method ToString:String()
'Just return the string attribute:
Return Self.complete_String' out_String
End Method
Method toString_Formatted_For_File:String()
Return Self.ToString()
End Method
Method toString_Formatted_For_Console:String()
Return Self.ToString()
End Method
End Type
Это очереди:
Type TThreadsafeQueue
'Predefined list.
Field list:TList
Method New()
Self.list = New TList
End Method
Method isEmpty:Byte()
Return Self.list.IsEmpty()
End Method
Method enqueue(to_Enqueue:Object)
'Add object to list
Self.list.AddLast(to_Enqueue)
End Method
Method dequeue:Object()
Return Self.list.RemoveFirst()
End Method
End Type
Вот метод, который добавляет сообщения в debugmanager:
Function enqueueMessage(message_To_Enqueue:TThreadsafeMessage)
'Test message for null pointer.
If(message_To_Enqueue = Null) Then
Throw New TNullpointer_Exception.NewException("'message_To_Enqueue' is NULL.", "TDebugmanager.bmx", ..
"TDebugmanager", "enqueueMessage")
EndIf
'Lock mutex for threadsafety.
LockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
'Enqeue message in the queue
TDebugmanager.getSingleton_Instance().message_Queue.enqueue(message_To_Enqueue)
'Tell the update thread there is a message
SignalCondVar(TDebugmanager.getSingleton_Instance().sleep_ConditionVariable)
'Free the mutex for update thread.
UnlockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
End Function
Теперь здесь (в настоящее время меньше) функция обновления debugmanager:
Function _update:Object(thread_Object:Object)
'Do this over and over till the queue is empty AND the debugmanager is shut down
Repeat
Local message_To_Process:TThreadsafeMessage = Null
'Lock mutex for thread safety
LockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
'Queue epmty...
If(TDebugmanager.getSingleton_Instance().message_Queue.isEmpty()) Then
'... Wait for a signal from the main thread
WaitCondVar(TDebugmanager.getSingleton_Instance().sleep_ConditionVariable, ..
TDebugmanager.getSingleton_Instance().queue_Mutex)
Else
'...Get the next message from the queue.
message_To_Process = TThreadsafeMessage(TDebugmanager.getSingleton_Instance().message_Queue.dequeue())
EndIf
'Unlock the mutex.
UnlockMutex(TDebugmanager.getSingleton_Instance().queue_Mutex)
'Check if the message is NULL.
If(message_To_Process = Null) Then
Throw "Got null message from queue."
EndIf
'Actually the _processMessage method is used. But for debugging
'it is commented out.
' TDebugmanager.getSingleton_Instance()._processMessage(message_To_Process)
'Write the message to the console.
'HERE is the error.
'See in the following description under the code section.
DebugLog("Message processed: " + message_To_Process.complete_String)
Until TDebugmanager.isFinished()
End Function
Итак, в том месте, где говорится в функции обновления, «ЗДЕСЬ есть ошибка». проблема заключается в следующем: если эта строка закомментирована или удалена, программа отлично работает на моем ноутбуке, и никаких ошибок не возникает. Но если эта строка существует, ошибка возникает в большинстве случаев. «EXCEPTION_ACCESS_VIOLATION» вызывается, например, когда: где-то происходит переток stackoverflow. Или когда вы пытаетесь получить доступ к объекту NULL. На самом деле все, что пытается читать или писать из запрещенной памяти. Странная вещь: только несколько строк раньше, я проверяю, является ли сообщение, которое я получил из очереди, NULL. Должно возникнуть ошибка, как вы можете видеть. Но этого никогда не бывает.
Кто-нибудь видел такое поведение раньше? Я не могу это объяснить. Как я уже сказал: отладка в этом случае очень тяжелая. Я мог бы просто разбить его на более мелкие классы и, наконец, код, который вы видите здесь. Я также не могу просто пойти шаг за шагом через программу с отладчиком, потому что тогда ошибка не возникает. Может кто-нибудь может подумать о чем-то, что может вызвать ошибку в этот момент?
Я знаю, это много кода, но я не мог сделать его короче.
Если вы действительно сомневаетесь в проблеме переполнения стека, попробуйте увеличить лимит стека для программы, а затем убедитесь, что вы все еще сталкиваетесь с проблемой на той же строке .../ –
В настоящее время я тестирую этот класс только с помощью тестовая программа. В этой тестовой программе некоторое количество сообщений добавляется в очередь и обрабатывается. Он также выходит из строя только с 10 сообщениями. И нет существенного увеличения использования ОЗУ. Я только хотел показать, сколько вещей есть, что может вызвать такой тип ошибки. Я не считаю, что это размер стека, потому что я написал гораздо больше программ с этим языком, не меняя размер стека или использование ОЗУ. – M0rgenstern