For Programmers: Free Programming Magazines  


Home > Archive > VC STL > March 2006 > Problem porting from STLPort 4.5 to VC++ 7?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Problem porting from STLPort 4.5 to VC++ 7?
Neal Davis

2006-03-14, 7:03 pm

I have an application C++/MFC originally written in eVC++ 3.0 for HPC2000.
It requires STLPort 4.5 builds and runs on HPC2000 (CE 3.0).

I have been asked to "port" the code to XP (embedded XP for tablet unit).
I'm not using STLPort, I am relying on VS .NET 2003 STL library. I have run
into what I "think" is some difference between STLPort and VC++ 7 STL?

The following code statment when executed in eVC++ 3.0 with STLPort puts
what appears to be the size of the vector in the last element + 1. In other
words my vector is 8 int's and this statement puts 32 in vector last element
+ 1:

std::pair<tAuditObservationItr,bool> lStatus =
mAuditObservations.insert( aAuditObservation );

After stepping through this statement the vector memory is shown below there
are 8 int elements and the last element + 1 is a 20 and it was just put
there after stepping through the above statement: I am assuming this 20 hex
(32 dec) is the size of the vector (in bytes 4 * 8) - I just don't really
know - all I know is I'm not putting this 0x20 there in my code anywhere?

00097868 87 12 00 00 B1 FF 00 00 ?...±ÿ..
00097870 B8 FB 09 00 57 B8 22 00 ¸û .W¸".
00097878 00 00 00 00 00 00 00 00 ........
00097880 00 00 00 00 31 97 97 00 ....1--.
00097888 20 00 00 00 00 00 00 00 .......

In VS .NET 2003 VC++ 7.1 when I step through this same statement as above
the last element + 1 of the vector still contains fd fd fd fd and does not
change. This value (0x20) in the case of eVC++ w/ STLPort is passed into a
parameter of a function latter on and apparently has been working for
several years okay. However in VC++ 7.1 the value passed is of course the fd
fd fd fd and then I get a memory exception some point latter on.

Did STLPort do something non standard on pair or insert that would do this
that the eVC++ software guys were relying on? I would like to fix the code
correctly so that if follows the STL standard.

There is a ton of code that I didn't to waste bandwidth posting, but let me
know what code segments you need to help me I can post class declarations
and implementations for any of the above.

I am very new to STL. I have been doing embedded C code and assembly most of
my life.

Thanks
Neal Davis


Igor Tandetnik

2006-03-14, 7:03 pm

Neal Davis <davisnNoSpam@NoSpamItronixDotcom> wrote:
> The following code statment when executed in eVC++ 3.0 with STLPort
> puts what appears to be the size of the vector in the last element +
> 1. In other words my vector is 8 int's and this statement puts 32 in
> vector last element + 1:
>
> std::pair<tAuditObservationItr,bool> lStatus =
> mAuditObservations.insert( aAuditObservation );


What vector are you talking about? From the statement,
mAuditObservations is almost certainly a std::set.

> After stepping through this statement the vector memory is shown
> below


std::set does not store its elements in contiguous memory. It's a
node-based container. Inspecting raw memory is unlikely to get you
anywhere.

> In VS .NET 2003 VC++ 7.1 when I step through this same statement as
> above the last element + 1 of the vector still contains fd fd fd fd
> and does not change. This value (0x20) in the case of eVC++ w/
> STLPort is passed into a parameter of a function latter on


How do you retrieve this value? If you reach directly into the memory
rather than using public methods of the class, you rely quite
unhealthily on internal implementation details of a particular STL
implementation. If this is the case, your code deserves to be broken.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Neal Davis

2006-03-14, 7:03 pm

Thanks for your response - you are correct there is a set involved, all I know at this time is there is a difference between the eVC with STLPort and the same code on VS .NET 2003 and it seems to be that 20 and the fd fd fd fd. I just don't know how or why yet?

let me post some more code and see if this helps -let me know if I'm leaving something out you need?

header file:

typedef set<CAuditObservation> tAuditObservations;
typedef set<CAuditObservation>::iterator tAuditObservationItr;
typedef set<CAuditedSegmentRecord> tSegmentRecords;

public:
tAuditObservations mAuditObservations;
tAuditObservationItr mEditItr;
tSegmentRecords mSegmentRecords;

void Insert( const CAuditObservation& aAuditObservation )
{
pair<tAuditObservationItr, bool> lStatus = mAuditObservations.insert( aAuditObservation );
if( !lStatus.second )
{
mAuditObservations.erase ( lStatus.first );
lStatus = mAuditObservations.insert( aAuditObservation );
}
mEditItr = lStatus.first;
};


Implementation file: This function calls the insert at the bottom:

void
CAuditSession::RecordDiscrepancy()
{
CAuditObservation lAuditObservation;

lAuditObservation.mIds[0] = mAuditComponentPtr[1]->IdSelected();
lAuditObservation.mIds[1] = mAuditComponentPtr[2]->IdSelected();
lAuditObservation.mIds[2] = mAuditComponentPtr[3]->IdSelected();
lAuditObservation.mIds[3] = mAuditComponentPtr[4]->IdSelected();
lAuditObservation.mIds[4] = mAuditComponentPtr[5]->IdSelected();
lAuditObservation.mIds[5] = mAuditComponentPtr[8]->IdSelected(); // ToolBoxParts is out of order
lAuditObservation.mIds[6] = mAuditComponentPtr[6]->IdSelected();
lAuditObservation.mIds[7] = mAuditComponentPtr[7]->IdSelected();
mFormDataPtr->mNoteBox.GetWindowText(lAuditObservation.mNote);
mFormDataPtr->mNoteBox.SetWindowText( _T(""));
mFileOut.Vehicle().Insert( lAuditObservation );
}


This function below is entered by a menu selection and at the mAuditComponentPtr[8]->... statement below a value of 0x20 is passed to the SelectById function parameter aId below in eVC++ with STLPort but with VS 2003 it passes fdfdfdfd?

void CAuditSession::SelectById( const CAuditObservation& aAuditObservation )
{
mAuditComponentPtr[1]->DescendantsReset();

if( aAuditObservation.mIds[0] )
{
mAuditComponentPtr[1]->SelectById(aAuditObservation.mIds[0]);
mAuditComponentPtr[2]->SelectById(aAuditObservation.mIds[1]);
mAuditComponentPtr[3]->SelectById(aAuditObservation.mIds[2]);
mAuditComponentPtr[4]->SelectById(aAuditObservation.mIds[3]);
mAuditComponentPtr[5]->SelectById(aAuditObservation.mIds[4]);
mAuditComponentPtr[8]->SelectById(aAuditObservation.mIds[8]);
mAuditComponentPtr[6]->SelectById(aAuditObservation.mIds[6]);
mAuditComponentPtr[7]->SelectById(aAuditObservation.mIds[7]);
mAuditComponentPtr[7]->DataRecordDescriptionBoxLButtonUp();

mFormDataPtr->mNoteBox.SetWindowText(aAuditObservation.mNote);
}
else
{
mFormDataPtr->mNoteBox.SetWindowText(_T(""));
mFormDataPtr->ButtonRecordDiscrepancyShow( SW_HIDE );

mAuditComponentPtr[1]->SelectById(0);
mAuditComponentPtr[1]->DataRecordDescriptionBoxLButtonUp();
}
mFormDataPtr->UpdateWindow();
};




void CAuditComponent::SelectById( int aId )
{
if( aId )
{
CDataRecord& lDataRecordRef = *DataRecordPtr();
lDataRecordRef = mDataFilePtr->DataRecordRange(mKey).Begin();
mListBoxIndex = 0 ;

for( ; IdSelected() != aId ; ++lDataRecordRef, ++mListBoxIndex );

mDataDisplayPtr->SetWindowText( (CString)(lDataRecordRef.Description()) );
mInstructionBoxPtr->SetWindowText( (CString)(lDataRecordRef.Instruction()) );

DescendantsInitialization();
}
else
{
mListBoxIndex = -1;
}
};


header for class CAuditObservation

class CAuditObservation
{
public:
typedef std::vector<int> tIds;
tIds mIds;
CString mNote;

CAuditObservation( ):mIds( 8,0),mNote( ){};
CAuditObservation(const CAuditObservation& aRef):mIds(aRef.mIds),mNote(aRef.mNote){};

bool operator<(const CAuditObservation& aRef) const{return mIds<aRef.mIds;};

operator CString() const
{ CString lRemark( mNote ); lRemark.SpanExcluding( _T("\n\r\v") );
CString lString;
lString.Format
( _T("02,%i,%i,%i,%i,%i,%i,%i,%i,%s")
, mIds[0], mIds[1], mIds[2], mIds[3], mIds[4], mIds[5], mIds[6], mIds[7]
, lRemark
);
return lString;
};
int Write( CFile* aFilePtr )const; //return & const & (no ref args) req'd for use with for_each
};


There is something else you should - this statement below:

mFileOut.mAuditedVehicles.back().mSegmentRecords.insert(mAuditComponentSegmentsPtr->IdSelected());

caused a bunch of compile errors in the STL functional file of VC 2003 that did not occur in eVC with STLPort to correct I had to do the following in VC 2003 that I am not certain is correct:

If I didn't define my own operator < as below then I got a bunch of compile errors I can post but I bet you guys already know what they were.

class CAuditedSegmentRecord
{
// typedef vector<int> tmId;
public:
//tmId mId;
int mId;
CAuditedSegmentRecord( ):mId( 0) /*,mMinutes( 0)*/{};
CAuditedSegmentRecord(const int aInt ):mId( aInt) /*,mMinutes( 0)*/{};
CAuditedSegmentRecord(const CAuditedSegmentRecord& aRef ):mId(aRef.mId) /*,mMinutes(aRef.mMinutes)*/{};
operator CString()const{ CString lString; lString.Format( _T("97,%i" ), mId ); return lString; };
int Write( CFile* aFilePtr )const; //return & const & (no ref args) req'd for use with for_each
friend bool operator<(const CAuditedSegmentRecord& left, const CAuditedSegmentRecord& right);
};
static inline bool operator<(const CAuditedSegmentRecord& left, const CAuditedSegmentRecord& right)
{
return left.mId < right.mId;
}; //NAD++ ???


CAuditSession::EndSegment()
{
mFileOut.mAuditedVehicles.back().mSegmentRecords.insert(mAuditComponentSegmentsPtr->IdSelected());
mAuditComponentSegmentsPtr->SegmentEnd();
mAuditComponentSegmentsPtr->DataRecordDescriptionBoxLButtonUp();
}


"Igor Tandetnik" <itandetnik@mvps.org> wrote in message news:%2352Wpi6RGHA.4792@TK2MSFTNGP14.phx.gbl...
> Neal Davis <davisnNoSpam@NoSpamItronixDotcom> wrote:
>
> What vector are you talking about? From the statement,
> mAuditObservations is almost certainly a std::set.
>
>
> std::set does not store its elements in contiguous memory. It's a
> node-based container. Inspecting raw memory is unlikely to get you
> anywhere.
>
>
> How do you retrieve this value? If you reach directly into the memory
> rather than using public methods of the class, you rely quite
> unhealthily on internal implementation details of a particular STL
> implementation. If this is the case, your code deserves to be broken.
> --
> With best wishes,
> Igor Tandetnik
>
> With sufficient thrust, pigs fly just fine. However, this is not
> necessarily a good idea. It is hard to be sure where they are going to
> land, and it could be dangerous sitting under them as they fly
> overhead. -- RFC 1925
>
>

Neal Davis

2006-03-14, 7:03 pm

Okay maybe it would be eaiser if I approach if from this direction:

The statement below causes no problems under eVC with STLPort
mFileOut.mAuditedVehicles.back().mSegmentRecords.insert(mAuditComponentSegmentsPtr->IdSelected());

However when compiled under VS .NET 2003 it causes the following errors below are produced: Futher more when the statement is broken down it appears to be something related to the mSegmentsRecords.insert(mAudiComponentSegmentsPtr->IdSelected()) section that is causing these errors. IdSelected() looks like this:

int CAuditComponent::IdSelected (){ return DataRecordPtr()->Id(); }


c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::queue<_Ty,_Container> &,const std::queue<_Ty,_Container> &)' : could not deduce template argument for 'const std::queue<_Ty,_Container> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::stack<_Ty,_Container> &,const std::stack<_Ty,_Container> &)' : could not deduce template argument for 'const std::stack<_Ty,_Container> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\stack(84) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::deque<_Ty,_Alloc> &,const std::deque<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::deque<_Ty,_Ax> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\deque(999) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Ax> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\string(148) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const T1 *' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\string(138) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Ax> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\string(128) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xtree(1170) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::list<_Ty,_Alloc> &,const std::list<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::list<_Ty,_Ax> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\list(991) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Ax> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\vector(915) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xutility(655) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const CAuditedSegmentRecord'
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(73) : see declaration of 'std::operator`<''
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\functional(139): error C2676: binary '<' : 'const CAuditedSegmentRecord' does not define this operator or a conversion to a type acceptable to the predefined operator


class CAuditedSegmentRecord
{
public:
int mId;
// int mMinutes;

CAuditedSegmentRecord( ):mId( 0)/*,mMinutes( 0)*/{};
CAuditedSegmentRecord(const int aInt ):mId( aInt)/*,mMinutes( 0)*/{};
CAuditedSegmentRecord(const CAuditedSegmentRecord& aRef ):mId(aRef.mId)/*,mMinutes(aRef.mMinutes)*/{};

// operator CString()const{ CString lString; lString.Format( _T("97,%i,%i"), mId, mMinutes ); return lString; };
operator CString()const{ CString lString; lString.Format( _T("97,%i" ), mId ); return lString; };

int Write( CFile* aFilePtr )const; //return & const & (no ref args) req'd for use with for_each
};


class CAuditedVehicle
{
typedef std::set<CAuditObservation> tAuditObservations;
typedef std::set<CAuditObservation>::iterator tAuditObservationItr;
typedef std::set<CAuditedSegmentRecord> tSegmentRecords;
public:
CAuditedVehicleHeader mHeader;
CAuditedVehicleRemark mRemark;
tAuditObservations mAuditObservations;
tAuditObservationItr mEditItr;
tSegmentRecords mSegmentRecords;
COleDateTime mTimeStart;
COleDateTime mTimeStop;
COleDateTimeSpan mTimeSpanPaused;

CAuditedVehicle
()
: mHeader ( )
, mRemark ( )
, mAuditObservations( )
, mEditItr (mAuditObservations.begin())
, mSegmentRecords ( )
, mTimeStart ( Now())
, mTimeStop ( Now())
, mTimeSpanPaused ( )
{};

CAuditedVehicle
( const CAuditedVehicle& aRef )
: mHeader (aRef.mHeader )
, mRemark (aRef.mRemark )
, mAuditObservations(aRef.mAuditObservations)
, mEditItr (aRef.mEditItr )
, mSegmentRecords (aRef.mSegmentRecords )
, mTimeStart (aRef.mTimeStart )
, mTimeStop (aRef.mTimeStop )
, mTimeSpanPaused (aRef.mTimeSpanPaused )
{};

CString Records()
{
int lPos = mAuditObservations.empty()?0:std::distance( mAuditObservations.begin(), mEditItr ) + 1;

CString lString; lString.Format( _T("%i : %i"), lPos, mAuditObservations.size() );

return lString;
};

void Insert( const CAuditObservation& aAuditObservation )
{
std::pair<tAuditObservationItr,bool> lStatus = mAuditObservations.insert( aAuditObservation );

if( !lStatus.second )
{
mAuditObservations.erase ( lStatus.first );
lStatus = mAuditObservations.insert( aAuditObservation );
}
mEditItr = lStatus.first;
};

CAuditObservation EditDelete()
{
if( !mAuditObservations.empty() )
{
tAuditObservationItr lNewItr( mEditItr );
if( ++lNewItr != mAuditObservations.end() ) // more remaining after the one deleted
{
mAuditObservations.erase( mEditItr );

mEditItr = lNewItr;
}
else // last in set
{
mAuditObservations.erase( mEditItr );

if( !mAuditObservations.empty() )
{
mEditItr = mAuditObservations.end(); --mEditItr;
}
else
{
mEditItr = mAuditObservations.begin();

return CAuditObservation();
}
}
return *mEditItr;
}
return CAuditObservation();
};
CAuditObservation EditNext()
{
if( !mAuditObservations.empty() )
{
if( !(++mEditItr!=mAuditObservations.end()) ) --mEditItr;

return *mEditItr;
}
return CAuditObservation();
};
CAuditObservation EditPrev()
{
if( !mAuditObservations.empty() )
{
if( mEditItr!=mAuditObservations.begin() ) --mEditItr;

return *mEditItr;
}
return CAuditObservation();
};
CAuditObservation EditBegin()
{
if( !mAuditObservations.empty() )
{
mEditItr = mAuditObservations.begin();

return *mEditItr;
}
return CAuditObservation();
};
CAuditObservation EditEnd()
{
if( !mAuditObservations.empty() )
{
mEditItr = mAuditObservations.end(); --mEditItr;

return *mEditItr;
}
return CAuditObservation();
};

int Write( CFile* aFilePtr )const; //return & const & (no ref args) req'd for use with for_each

void TimerStop(){ mTimeStop = Now(); mHeader.mDurationMinutes = ((mTimeStop-mTimeStart)-mTimeSpanPaused).GetTotalMinutes();};

static COleDateTime Now(){ SYSTEMTIME lT; ::GetLocalTime(&lT); return COleDateTime(lT); };
};



"Igor Tandetnik" <itandetnik@mvps.org> wrote in message news:%2352Wpi6RGHA.4792@TK2MSFTNGP14.phx.gbl...
> Neal Davis <davisnNoSpam@NoSpamItronixDotcom> wrote:
>
> What vector are you talking about? From the statement,
> mAuditObservations is almost certainly a std::set.
>
>
> std::set does not store its elements in contiguous memory. It's a
> node-based container. Inspecting raw memory is unlikely to get you
> anywhere.
>
>
> How do you retrieve this value? If you reach directly into the memory
> rather than using public methods of the class, you rely quite
> unhealthily on internal implementation details of a particular STL
> implementation. If this is the case, your code deserves to be broken.
> --
> With best wishes,
> Igor Tandetnik
>
> With sufficient thrust, pigs fly just fine. However, this is not
> necessarily a good idea. It is hard to be sure where they are going to
> land, and it could be dangerous sitting under them as they fly
> overhead. -- RFC 1925
>
>

Igor Tandetnik

2006-03-15, 3:58 am

"Neal Davis" <davisnNoSpam@NoSpamItronixDotcom> wrote in message
news:%23V%23px%236RGHA.4960@TK2MSFTNGP12.phx.gbl
> mAuditComponentPtr[8]->SelectById(aAuditObservation.mIds[8]);


Note mIds[8]

> header for class CAuditObservation
>
> class CAuditObservation
> {
> public:
> typedef std::vector<int> tIds;
> tIds mIds;
> CString mNote;
>
> CAuditObservation():mIds(8,0),mNote( ){};


Note that mIds is created to have 8 elements, indexed 0 through 7.

You are accessing an element out of bounds.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Neal Davis

2006-03-15, 7:02 pm

Igor;

Yes I see that - well pigs really can fly given enough thrust but you really
can't access an array out of bounds no matter how much thrust!

Thanks!

Neal Davis



"Igor Tandetnik" <itandetnik@mvps.org> wrote in message
news:OlKyqx%23RGHA.4960@TK2MSFTNGP12.phx.gbl...
> "Neal Davis" <davisnNoSpam@NoSpamItronixDotcom> wrote in message
> news:%23V%23px%236RGHA.4960@TK2MSFTNGP12.phx.gbl
>
> Note mIds[8]
>
>
> Note that mIds is created to have 8 elements, indexed 0 through 7.
>
> You are accessing an element out of bounds.
> --
> With best wishes,
> Igor Tandetnik
>
> With sufficient thrust, pigs fly just fine. However, this is not
> necessarily a good idea. It is hard to be sure where they are going to
> land, and it could be dangerous sitting under them as they fly
> overhead. -- RFC 1925
>



Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com