为什么多个变量会公用一个地址空间呢?

sad_4978 2005-03-25 11:18:01
我一起定义了5个CString 对象。初始化“”,可为什么这5个对象却在一个地址空间中。
CString strComPortName = "";
CString strBaudRate = "";
CString strParity = "";
CString strParityMethod = "";
CString strByteSize = "";
CString strStopBits = "";
然后作处理,带了一个上午,也没看到有效值。后来发现是几个变量公用了一个地址空间。所以他们得值总是一样的。这是怎么回事?请大家帮忙解决。谢谢!
...全文
193 点赞 收藏 20
写回复
20 条回复
Featured 2005年03月27日
cut9讲的有道理

那么 Eliminate Duplicate String 又是干什么的呢?

ps 这个问题楼主可以结贴了,上面的问题我可以考虑另开帖给分
回复 点赞
sad_4978 2005年03月25日
不同的初值不一样。
回复 点赞
cut9 2005年03月25日
当然可能一样,而且99%一样。你定义的时候,给他们不同的初始值,看看一样不!
回复 点赞
poooorgun 2005年03月25日
刚定义完时,地址一样吗?
回复 点赞
cut9 2005年03月25日
这5个CString的取值一样的时候,是可能m_pchData一样的。
你把它们的值弄得不一样看看。我估计你是在开头他们的值一样的时候看的m_pchdata.
回复 点赞
sad_4978 2005年03月25日
在调试的时候不是可以看到m_pchData指针嘛,我说的就是这个。
回复 点赞
cut9 2005年03月25日
那你是根据什么说他们的指针一样呢?
回复 点赞
sad_4978 2005年03月25日
CString strComPortName;
CString strBaudRate;
CString strParity;
CString strParityMethod;
CString strByteSize;
CString strStopBits;
for(int i = 1;i < MAX_SerialPort_Number + 1;i++)
{
CString strSection = "";
strSection.Format(_T("SerialPort%d"), i);
strComPortName = "";
BOOL bResult = FALSE;
bResult = ReadIniFlie(strSection, "ComPortNum", strINIPath,
MAX_BUFFER, strComPortName);

if(!bResult)
{
return FALSE;
}
else
{
bResult = FALSE;
}

if(strComPortName.Compare("0") == 0)
{
continue;
}

strBaudRate.Empty();
strBaudRate = "";
bResult = ReadIniFlie(strSection, "BaudRate", strINIPath,
MAX_BUFFER, strBaudRate);

if(!bResult)
{
return FALSE;
}
else
{
bResult = FALSE;
}

strParity.Empty();
strParity = "";
bResult = ReadIniFlie(strSection, "Parity", strINIPath,
MAX_BUFFER, strParity);

if(!bResult)
{
return FALSE;
}
else
{
bResult = FALSE;
}
strParityMethod.Empty();
strParityMethod = "";
if(strParity.Compare("1") == 0)
{

bResult = ReadIniFlie(strSection, "ParityMethod", strINIPath,
MAX_BUFFER, strParityMethod);

if(!bResult)
{
return FALSE;
}
else
{
bResult = FALSE;
}
}
else
{
strParityMethod = "0";
}

strByteSize.Empty();
strByteSize = "";
bResult = ReadIniFlie(strSection, "ByteSize", strINIPath,
MAX_BUFFER, strByteSize);

if(!bResult)
{
return FALSE;
}
else
{
bResult = FALSE;
}

strStopBits.Empty();
strStopBits = "";
bResult = ReadIniFlie(strSection, "StopBits", strINIPath,
MAX_BUFFER, strStopBits);

if(!bResult)
{
return FALSE;
}
else
{
bResult = FALSE;
}
回复 点赞
surstar 2005年03月25日

CString strComPortName;
CString strBaudRate;
CString strParity;
CString strParityMethod;
CString strByteSize;
CString strStopBits;

这样不就行了,不知道你要做什么~
回复 点赞
cut9 2005年03月25日
贴上来看看,完成的程序.10有89是你自己搞错了
回复 点赞
sad_4978 2005年03月25日
我写错了,是这样,他们里面包含的指针地址一样!怎么回事?怎么解决?
回复 点赞
cut9 2005年03月25日
可以结账了吗
回复 点赞
cut9 2005年03月25日
刚又想了一下:

char x[] = "abcd";
char y1[] = "ab";
char y2[] = "cd";
char y[5];
strcpy(y,y1);
strcat(y,y2);
CString A = x;
CStrin B = y;

A,B指的应该不一样。察看CString的源代码。如果这样,指针是一样的

看这段代码,经过测试的:

CString T1= "abcd";
CString A = T1;
CString B = "123";

//这儿看, A,B的m_pchData不一样

B = T1;

//这儿看, A,B的m_pchData一样。B指到A的 m_pchData.


这不是编译器做的事情了。

C/C++中,Eliminate Duplicat String如果是YES,那么(不一定是CString,标准C/C++没有CString)
这段代码:

char x[] = "abcd";
char y[] = "abcd";
如果改了y,x也被改了。





回复 点赞
koko1998 2005年03月25日
以前也遇到过,后来这样做的。
CString strComPortName = "";
CString strBaudRate = "";

...........
strComPortName = (LPCSTR)strBaudRate ;
回复 点赞
cut9 2005年03月25日
Featured,Eliminate Duplicat String 不是对CString来用的。它是c/c++编译器自己的选项。
GCC也有这个。

给你看CString的源代码吧(为了说明问题,我重新启动另外一个系统,找CSTring源代码^=^)

MICROSOFT VISUAL STUDIO\VC98\MFC\SRC\STREX.CPP

int CString::Remove(TCHAR chRemove)
{
CopyBeforeWrite();

LPTSTR pstrSource = m_pchData;
LPTSTR pstrDest = m_pchData;
LPTSTR pstrEnd = m_pchData + GetData()->nDataLength;

while (pstrSource < pstrEnd)
{
if (*pstrSource != chRemove)
{
*pstrDest = *pstrSource;
pstrDest = _tcsinc(pstrDest);
}
pstrSource = _tcsinc(pstrSource);
}
*pstrDest = '\0';
int nCount = pstrSource - pstrDest;
GetData()->nDataLength -= nCount;

return nCount;
}

void CString::TrimRight(LPCTSTR lpszTargetList)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)

CopyBeforeWrite();
LPTSTR lpsz = m_pchData;
LPTSTR lpszLast = NULL;

while (*lpsz != '\0')
{
if (_tcschr(lpszTargetList, *lpsz) != NULL)
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
lpsz = _tcsinc(lpsz);
}

if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}

void CString::TrimRight(TCHAR chTarget)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)

CopyBeforeWrite();
LPTSTR lpsz = m_pchData;
LPTSTR lpszLast = NULL;

while (*lpsz != '\0')
{
if (*lpsz == chTarget)
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
lpsz = _tcsinc(lpsz);
}

if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}

void CString::TrimRight()
{
// find beginning of trailing spaces by starting at beginning (DBCS aware)

CopyBeforeWrite();
LPTSTR lpsz = m_pchData;
LPTSTR lpszLast = NULL;

while (*lpsz != '\0')
{
if (_istspace(*lpsz))
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
lpsz = _tcsinc(lpsz);
}

if (lpszLast != NULL)
{
// truncate at trailing space start
*lpszLast = '\0';
GetData()->nDataLength = lpszLast - m_pchData;
}
}

void CString::TrimLeft(LPCTSTR lpszTargets)
{
// if we're not trimming anything, we're not doing any work
if (SafeStrlen(lpszTargets) == 0)
return;

CopyBeforeWrite();
LPCTSTR lpsz = m_pchData;

while (*lpsz != '\0')
{
if (_tcschr(lpszTargets, *lpsz) == NULL)
break;
lpsz = _tcsinc(lpsz);
}

if (lpsz != m_pchData)
{
// fix up data and length
int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
GetData()->nDataLength = nDataLength;
}
}

void CString::TrimLeft(TCHAR chTarget)
{
// find first non-matching character

CopyBeforeWrite();
LPCTSTR lpsz = m_pchData;

while (chTarget == *lpsz)
lpsz = _tcsinc(lpsz);

if (lpsz != m_pchData)
{
// fix up data and length
int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
GetData()->nDataLength = nDataLength;
}
}

void CString::TrimLeft()
{
// find first non-space character

CopyBeforeWrite();
LPCTSTR lpsz = m_pchData;

while (_istspace(*lpsz))
lpsz = _tcsinc(lpsz);

if (lpsz != m_pchData)
{
// fix up data and length
int nDataLength = GetData()->nDataLength - (lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
GetData()->nDataLength = nDataLength;
}
}


很多很多,只要涉及到CString修改的,必定 CopyBeforeWrite.

关于Eliminate Duplicat String,可以另开贴子讨论.QQ 183344050 ^=^




回复 点赞
cut9 2005年03月25日
Featured,Eliminate Duplicat String 不是对CString来用的。它是c/c++编译器自己的选项。
GCC也有这个。

给你看CString的源代码吧(为了说明问题,我重新启动另外一个系统,找CSTring源代码^=^)


回复 点赞
Featured 2005年03月25日
应该是编译器优化的问题

project - settings - c/C++ - customize -Eliminate Duplicat String (消除复制字符串)选项
回复 点赞
cut9 2005年03月25日
oyljerry ,不是编译器优化。
编译器优化是静态(编译态)的工作,MFC管理内存是运行时的工作。是动态的。

以下这段代码可能造成 字符串 A,B 的m_pchData地址一样:

char x[] = "abcd";
char y1[] = "ab";
char y2[] = "cd";
char y[5];
strcpy(y,y1);
strcat(y,y2);
CString A = x;
CStrin B = y;
...检查 A,B的m_pchData,很有可能一样的了。

编译器是不知道 x 和 y一样的,因为没有运行。它只作词法分析,语法分析,不做
程序计算。






回复 点赞
cut9 2005年03月25日
这就对了。我给你讲讲道理吧。
CString用了节省内存的办法。如果A,B字符串的值一样,那么MFC可能(只是可能!)让A,B指向同一个地止。但是,如果这时候你改变B的值,MFC会马上给B分配新的地址,拷贝一份新的值进去,让你
修改。
这就是很多操作系统,比如unix,windows都在早期提出的概念:写时拷贝。(Copy-On-Write).
节省内存。

再给你讲深点吧!
一个应用程序,比如myapp.exe,你启动它,它会有数据区(data section),代码区(code section)
那么你再启动myapp.exe一次。就启动2个了吧?这2个刚开始的data section极有可能是一个地方!
当然,如果你修改了data section,比如你按了个按钮,作了一个操作,改了数据,那么windows
系统会自己拷贝一个新的data section,作为第二个启动的myapp.exe使用。

当然罗,windows的写时拷贝和MFC管理CString的写时拷贝不是一个层次,只是概念一样。

快结账啊!在线等!^=^


回复 点赞
oyljerry 2005年03月25日
编译器作了优化
回复 点赞
发动态
发帖子
VC/MFC
创建于2007-09-28

7898

社区成员

42.1w+

社区内容

VC/MFC相关问题讨论
社区公告
暂无公告