2015-08-19 2 views
2

В настоящее время существует одно исключение из программы, написанной C++, и выполняется под окнами.Каким образом это нарушение доступа к адресу?

вот информация о минимальном дампе в журналах.

08/12/15 04:37:19 I New Information for UID 2d936a, FloorLoc F1505 
08/12/15 04:37:19 E >>>>> EXCEPTION: Access Violation while trying to read address 20203567 
[Fault address: 004AF945 01:000AE945 C:\Program Files (x86)\MySystems\WPR.exe 00400000] <<<<< 
Call stack: 
Load addr Address Frame  Logical addr Module 
00400000 004AF945 0588F8CC 0001:000AE945 C:\Program Files (x86)\MySystems\WPR.exe 
00400000 004A89A4 0588FAEC 0001:000A79A4 C:\Program Files (x86)\MySystems\WPR.exe 

Согласно логическому адру и .map файла, я могу найти коды, где брошенные это исключение.

if (TempMSE->m_elem == NULL) 
{ 
    TempMSE->m_elem = new Element(element); 
    TempMSE->m_elem->SetLocation(FloorLoc); 
    LoggerInfo("New Information for UID %x, FloorLoc %s", Id, FloorLoc.ToString(buf)); 
} 

TempMSE->m_elem->SetValue0(CIN_0, 0); // this exception is thrown here!!! through logical address 0001:000AE945 

Кажется, что m_elem получает один адрес от new оператора, и никаких исключений для SetLocation вызова функции. Также корректно отображается следующий журнал.

Почему у нас возникает одно исключение из SetValue0? Здесь функция SetValue0

void SetValue0(INDEX idx, DWORD val)  
{ 
    if (idx >= 0 && idx < MAX_INDEX){ 
     if(val != m_Info[idx]) 
     { 
      m_Info[idx] = val; 
     } 
    } 
} 

m_Info одна переменная массива в Element, а размер ее составляет MAX_INDEX.

С другой стороны, адрес 0x20203567 кажется удобным для чтения адресом, как его можно считать нарушением?

Редактировать

Добавить больше информации здесь

class Element { 
    // other function here... 

private: 
    FloorLocation m_FloorLoc; 
    DWORD m_Info[MAX_INDEX]; 
    bool   m_Dirty; 
}; 

Element::Element(const Element& elem) { 
    m_FloorLoc = elem.m_FloorLoc; 
    for (int i = 0; i < MAX_INDEX; ++i) 
     m_Info[i] = elem.m_Info[i]; 
    m_Dirty = elem.m_Dirty; 
} 

class FloorLocation { 
    // other function here... 
private: 
    FloorId m_floorloc; 
}; 

FloorLocation::FloorLocation(const FloorLocation& loc) 
{ 
    memset(&m_floorloc, ' ', 8); // space filled 

    if(loc.m_floorloc.id[0] != 0) 
    { 
     memcpy(m_floorloc.id, loc.m_floorloc.id, 8); 

     // eliminate nulls 
     for(int ndx=0; ndx < 8; ndx++) 
     { 
      if(m_floorloc.id[ndx] == 0) 
       m_floorloc.id[ndx]=' '; 
     } 
    } 
} 

typedef struct { 
    char id[8]; 
} FloorId; 
+0

Это может произойти, если ' TempMSE' или 'TempMSE-> m_elem' не является допустимым адресом или висящим указателем. _e.g._ unintialised или удален и не установлен в NULL, или если 'm_elem' был разбит в буфере, переполненном где-то еще внутри объекта. – paddy

+3

« 20203567 »выглядит как символы ASCII. Вы проверили, что указатель 'm_elem' указывает на (записываемый) ОЗУ вместо некоторых данных readonly const? – harper

+0

@harper, вы хотите проверить возврат указателя 'new Element'? – zangw

ответ

1

Эти вопросы немного трудно ответить. Я дал некоторые идеи в комментариях, о которых я расскажу здесь. Вот те вещи, которые я ищу, когда у меня есть подобные журналы сбоев без каких-либо других указаний.

Нарушение прав доступа на чтения в этом месте предлагает один из следующих действий:

  • TempMSE не является действительным указателем, и исключение при попытке получить m_elem от него;

  • TempMSE->m_elem не является действительным, и исключение внутри SetValue0 при попытке проверить значение m_Info[idx].

В последнем случае это может произойти, если вы удалите TempMSE->m_elem где-то, но не устанавливать его в NULL. Если для этого удаления отвечает другой поток, возможно, у вас есть условие гонки здесь, где он должен быть установлен в NULL, но этот код выполняется первым.

Другая возможность состоит в том, чтобы либо TempMSE, либо TempMSE->m_elem были повреждены где-то по пути. Это может быть результатом переполнения буфера внутри TempMSE (если у вас есть массивы) или в основном любое неопределенное поведение, которое происходит вблизи этих указателей в памяти. Если TempMSE находится в стеке, тогда найдите любую потенциальную проблему.

Я не хочу заполнять этот ответ другими видами спекуляций (например, кучевое повреждение), но, надеюсь, это дает вам несколько возможностей попробовать. Основной перечень общих преступников заключается в следующем:

  • ошибки кодирования (не инициализация или сброса значения)
  • вопросов многопоточности, условие гонки ...
  • непредсказуемого поведения или перерасход громя данные

Удачи!

1

Я не могу сказать, что на самом деле не так, но я бы разобрал код в 0x004AF945 и несколько инструкций раньше и попытаюсь понять, в какой части функции сбоя.

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

Это только предположение, но я подозреваю, что TempMSE->m_elem - это то, что содержит значение 0x20203567, и, таким образом, NOT NULL, когда он пытается получить к нему доступ, что означает, что ведение журнала не выполняется. [Очевидно, это основано на том, какой код вы показывали до сих пор, и если есть регистрация до/после этого показа, это не так, моя вторая догадка заключается в том, что m_info как-то не так ...

+0

(little endian) '20203567'' 'c5" ', а не' 'C#" '. – harper

+0

Нет, это '' g5 "'. – Henrik

+0

@ Хенрик. Ага. Я сделал разные неправильные догадки. – harper

Смежные вопросы