У меня есть следующий код, и для жизни я не могу понять, почему было исключение нарушения доступа? Я даже удалил все файлы OBJ, TDS etc и поместил их в новый проект, но все же происходит нарушение доступа.Сумасшедшее нарушение доступа в C++ Builder 6
По существу, этот код отображает TListView в TFrame и должен показывать различные текущие времена по всему миру для разных часовых поясов.
Примечание: код в C++ Builder 6.
Может кто-то помочь?
BLOODY-HELL-UPDATE: Решено. Я не должен добавлять элементы в TListView в конструкторе TFrame. DUMB DUMB DUMB.
MAJOR UPDATE: Кажется, что когда UpdateTimes() вызывается с помощью таймера, «Li-> Удаление» свойство имеет значение ИСТИНА. При вызове вне таймера это ЛОЖЬ. Теперь почему «li-> Deleting» устанавливается в «true», потому что он вызывается из таймера? Если я делаю:
if(li->Deleting == false)
{
li->Caption = "abcd";
}
Оно не ввести, если(), когда UpdateTimes() вызывается из таймера ...... argggggh !!!
UPDATE: Похоже, если я вызову UpdateTimes() вне TTimer, он отлично работает. Но при вызове с таймера он вызывает нарушение доступа. Что дает?
Заголовочный файл:
#ifndef CurrentTimes_FrameH
#define CurrentTimes_FrameH
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <ComCtrls.hpp>
#include <list>
using namespace std;
//---------------------------------------------------------------------------
struct LOCATIONTIMEINFORMATION
{
AnsiString TimeZoneName;
AnsiString PlaceName;
int UtcOffsetMinutes;
TListItem* ListItem;
};
//---------------------------------------------------------------------------
class TCurrentTimesFrame : public TFrame
{
__published: // IDE-managed Components
TTimer *Timer;
TListView *ListView;
void __fastcall TimerTimer(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TCurrentTimesFrame(TComponent* Owner);
//---------------------------------------------------------------------------
//User Code
//---------------------------------------------------------------------------
private:
list<LOCATIONTIMEINFORMATION> FTimeInformation;
typedef list<LOCATIONTIMEINFORMATION>::iterator LocationTimeInformationItr;
public:
void AddTimeInformation(LOCATIONTIMEINFORMATION lti);
void UpdateTimes();
};
//---------------------------------------------------------------------------
#endif
CPP файла:
#include <vcl.h>
#pragma hdrstop
#include "CurrentTimes_Frame.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
__fastcall TCurrentTimesFrame::TCurrentTimesFrame(TComponent* Owner): TFrame(Owner)
{
Timer->Enabled = false;
<strike>{
LOCATIONTIMEINFORMATION lti;
lti.TimeZoneName = "UTC";
lti.PlaceName = "Near Greenwich, England";
lti.UtcOffsetMinutes = 0;
AddTimeInformation(lti);
}</strike>
//UPADTED: Don't add TListItem from constructor
}
//---------------------------------------------------------------------------
void TCurrentTimesFrame::AddTimeInformation(LOCATIONTIMEINFORMATION lti)
{
TListItem* li = ListView->Items->Add();
li->Caption = lti.TimeZoneName;
li->SubItems->Add(lti.PlaceName);
li->SubItems->Add(lti.UtcOffsetMinutes);
li->SubItems->Add("<time will come here>");
lti.ListItem = li;
ShowMessage(AnsiString(lti.ListItem->ClassName())); //Correctly shows "TListItem"
FTimeInformation.push_back(lti);
{
LOCATIONTIMEINFORMATION temp = FTimeInformation.front();
ShowMessage(AnsiString(temp.ListItem->ClassName())); //Correctly shows "TListItem"
}
Timer->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TCurrentTimesFrame::TimerTimer(TObject *Sender)
{
UpdateTimes();
}
//---------------------------------------------------------------------------
void TCurrentTimesFrame::UpdateTimes()
{
Timer->Enabled = false;
TListItem* li;
for(LocationTimeInformationItr itr=FTimeInformation.begin();itr!=FTimeInformation.end();itr++)
{
li = itr->ListItem;
ShowMessage(AnsiString(li->ClassName())); //Access Violation:
/*
ShowMessage() above shows:
---------------------------
Debugger Exception Notification
---------------------------
Project XX.exe raised exception class EAccessViolation with message 'Access violation at address 4000567D in module 'rtl60.bpl'. Read of address 00000000'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
*/
}
Timer->Enabled = true;
}
//---------------------------------------------------------------------------
UPDATE пример кода demo'ing, что список принимает элементы, как копии, а не ссылаться. (Насколько я могу видеть, пожалуйста, поправьте меня, если им сделать какую-то ошибку в коде ниже)
@Craig Young:
Я запутался ... Я думал, что будет Структуры добавлены в список как копия не в качестве ссылки? Пожалуйста, взгляните на код ниже, кажется, что копия делается? Или я пропустил что-то рудиментарное? Или ошибка кодирования ниже?
void PopulateData()
{
AnsiString DebugText;
list<LOCATIONTIMEINFORMATION> Data;
LOCATIONTIMEINFORMATION OnStack;
//Prints "junk"
DebugText.sprintf("%s,%s,%d,%d",OnStack.TimeZoneName,OnStack.PlaceName,OnStack.UtcOffsetMinutes,(int)OnStack.ListItem);
OnStack.TimeZoneName = "UTC";
OnStack.PlaceName = "Near Greenwich, England";
OnStack.UtcOffsetMinutes = 10;
OnStack.ListItem = (TListItem*)20;
//OnStack:
DebugText.sprintf("%s,%s,%d,%d",OnStack.TimeZoneName,OnStack.PlaceName,OnStack.UtcOffsetMinutes,(int)OnStack.ListItem);
//Add data to list
Data.push_back(OnStack);
//Get struct from list
LOCATIONTIMEINFORMATION InList = Data.front();
//OnStack:
DebugText.sprintf("%s,%s,%d,%d",OnStack.TimeZoneName,OnStack.PlaceName,OnStack.UtcOffsetMinutes,(int)OnStack.ListItem);
//InList:
DebugText.sprintf("%s,%s,%d,%d",InList.TimeZoneName,InList.PlaceName,InList.UtcOffsetMinutes,(int)InList.ListItem);
//Change OnStack
OnStack.TimeZoneName = "NONE";
OnStack.PlaceName = "USA";
OnStack.UtcOffsetMinutes = 50;
OnStack.ListItem = (TListItem*)90;
//OnStack:
DebugText.sprintf("%s,%s,%d,%d",OnStack.TimeZoneName,OnStack.PlaceName,OnStack.UtcOffsetMinutes,(int)OnStack.ListItem);
//InList:
DebugText.sprintf("%s,%s,%d,%d",InList.TimeZoneName,InList.PlaceName,InList.UtcOffsetMinutes,(int)InList.ListItem);
//Change InList:
InList.TimeZoneName = "SOME";
InList.PlaceName = "BRAZIL";
InList.UtcOffsetMinutes = 66;
InList.ListItem = (TListItem*)88;
//OnStack:
DebugText.sprintf("%s,%s,%d,%d",OnStack.TimeZoneName,OnStack.PlaceName,OnStack.UtcOffsetMinutes,(int)OnStack.ListItem);
//InList:
DebugText.sprintf("%s,%s,%d,%d",InList.TimeZoneName,InList.PlaceName,InList.UtcOffsetMinutes,(int)InList.ListItem);
}
РЕШЕН. ОК. Я узнал, что DONT добавляет элементы в TListView в конструкторе. Как DUMB. – Liao
Не совсем; ваше «решение», возможно, изменило что-то другое, но создание TListItems в конструкторе не должно по своей сути вызывать проблемы. Пожалуйста, проверьте мой подробный ответ. –
Моя ошибка. Я имею тенденцию иметь больше мышления Дельфы; и без STL наш TList всегда будет хранить элементы по ссылке, если не будет сделано особых усилий. Тем не менее, я протестировал ваш оригинальный код, и он отлично работает, поэтому я думаю, что ваша ошибка в другом месте. Укажите, как вы используете фрейм. –