我写了一个windows的程序,其中用到了全局变量,我将它单独放到了一个类里面,是这么定义的:
char* theFileName;
然后在外部文件里面定义为extern型的变量。当程序第一次给theFileName赋值的时候,一切正常,查看地址是0x0012f060,里面的内容也是正常的:“E:\computer\source code\mycode_C++\WTL\input\default.inp”;
但是,当程序在另外一个类里面又要取这个值的时候,地址还是0x0012f060,但里面的内容却变成了“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”这是为什么呢?
-------------------------------------------------
<hr>
另外,我又写了一个最简单的MFC程序,同样是有一个全局变量,同样是在一个类里面给全局变量赋值,在另外一个类里面取值,却一点错误都没有,究竟是为什么呢?有什么窍门?
char* theFileName;
然后在外部文件里面定义为extern型的变量。当程序第一次给theFileName赋值的时候,一切正常,查看地址是0x0012f060,里面的内容也是正常的:“E:\computer\source code\mycode_C++\WTL\input\default.inp”;
但是,当程序在另外一个类里面又要取这个值的时候,地址还是0x0012f060,但里面的内容却变成了“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”这是为什么呢?
-------------------------------------------------
<hr>
另外,我又写了一个最简单的MFC程序,同样是有一个全局变量,同样是在一个类里面给全局变量赋值,在另外一个类里面取值,却一点错误都没有,究竟是为什么呢?有什么窍门?
是否是这样开辟一个空间赋值给theFileName ,然后再对theFileName指向得地址填充字符串呢?如果是这样得话,肯定不会有问题!但是如果你只是把theFileName 指向一个局部得变量得地址,那么一旦超出得局部变量的作用域局部变量内容可能就没了!可能就会出现你的问题!
那是类的成员变量。
如果非要放在类里,改成Static类型
按照你的意思。应该用前面 handwolf(青松崖) 提到的方法,在堆中分配内存,
char * theFileName = new char[128];
或者直接把指针改为 char theFileName[128];这样全局区会分配128个字节的空间。可以直接用theFileName 指向这个字符串。
#pragma onceclass GlobalVars
{
public:
GlobalVars(void);
~GlobalVars(void);
public:
char* theInputFile;
};extern GlobalVars theGlobalVars;____________________________________________________________
#include "StdAfx.h"
#include "MyGlobalVars.h"GlobalVars::GlobalVars(void)
{
}GlobalVars::~GlobalVars(void)
{
}
GlobalVars theGlobalVars;
___________________________________________________________________
看了前面的留言,似乎觉得这样是有问题的。
但是,如果我有很多个全局变量,但是又想以很好的方式把它组织起来,应该用什么方法比较好呢?
***********************************************************************
#pragma onceclass CMyGlobalVars
{
public:
CMyGlobalVars(void);
~CMyGlobalVars(void);
public:
char* theInputFile;
//之所以采用这种方式,是因为我有很多的全局变量,但是我又不想它们显得很乱,
//所以将它们全部放到一个CMyGlobalVars类里面
};extern CMyGlobalVars theGlobalVars;
/*********************************************************************/#include "StdAfx.h"
#include ".\myglobalvars.h"CMyGlobalVars::CMyGlobalVars(void)
{
}CMyGlobalVars::~CMyGlobalVars(void)
{
}CMyGlobalVars theGlobalVars;/*********************************************************************/
// temp4Dlg.cpp : 实现文件......
#include "MyGlobalVars.h"void Ctemp4Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
char* test = new char[256];
test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
theGlobalVars.theInputFile = test;
test = NULL; //之所以这样做,只是好奇:)
}
void Ctemp4Dlg::OnBnClickedButton2() //执行正常
{
// TODO: 在此添加控件通知处理程序代码
CStatic *pStatic;
pStatic = (CStatic*) GetDlgItem(IDC_VAR);
pStatic->SetWindowText(theGlobalVars.theInputFile);
}/*********************************************************************/
// temp4.cpp : 定义应用程序的类行为。.......
#include "MyGlobalVars.h"void Ctemp4App::OnBnClickedButton3() //执行正常
{
// TODO: 在此添加控件通知处理程序代码
AfxMessageBox(theGlobalVars.theInputFile);
}
***********************************************************************
test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
theGlobalVars.theInputFile = test;
===========================================================
已经分配空间了,是不会出错的。你原来的windows程序的代码是什么样的??
test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp"; //test重新赋值 ,指针已改变
theGlobalVars.theInputFile = test;
且test没有释放
你可以用strcpy,或者memcpy
char* test = new char[256];strcpy( test , "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp" );
test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
的代码都写的出来,不知道你的C++是怎么学的
【 char* test = new char[256];
test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
theGlobalVars.theInputFile = test;
test = NULL; //之所以这样做,只是好奇:)
】只是好玩!
我的程序完全可以写成这样:void Ctemp4Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
theGlobalVars.theInputFile = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
}一点问题也没有。那么我的问题是,为什么我在这个最简单的程序里面可以用这种方式使用我的CMyGlobalVars类,但是,在我别的程序里面却不行呢? Lancelet(文昌鱼) :
请问,你的C++又是怎么学的呢?能否解释我这里全部变量的问题?
这些数据是存在栈中的
函数执行完后,栈里的数据就没有了
我给出了代码的示例程序,运行结果是完全正确的啊
如:
char *test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
生成的汇编为:
_DATA SEGMENT
$SG579 DB 'E:\work\computer\source code\mycode_C++\WTL\MyOopic\inpu'
DB 't\default.inp', 00H
ORG $+2
$SG580 DB '%x', 0aH, 00H
$SG581 DB '%x', 0aH, 00H
_DATA ENDS
...
mov DWORD PTR _test$[ebp], OFFSET FLAT:$SG579
; Line 6
mov eax, DWORD PTR _test$[ebp]我估计还是你程序的问题,可能在程序的某个地方,将theGlobalVars.theInputFile所指的数据区破坏了
theGlobalVars.theInputFile="E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
我可以保证绝对没问题,因为"E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp"这个是放在代码段中,除非程序结束,要不然就不会被摧毁
test = "E:\\";//test指向临时的栈地址(比如0x0046e020)
theGlobalVars.theInputFile = test;//此时把临时的栈地址赋给了theInputFile
test = NULL;//这个是没关系的,只是把指针指向空!但是你要记得释放开辟的堆空间!上面的代码结束后,象我在前面说的一样,可能跳出了栈地址(比如0x003c0a28)的作用域,这样0x003c0a28中的内容就不会保留下来,所以出现了“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”楼主明白了没有?要把指针操作和几个内存空间弄清楚(堆和栈等等)
看我上面的汇编,VC不会把字符常量放在code段,所以有能被改写,如:
#include <stdio.h>char *test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
main()
{
test[0]='s';
printf("%s\n",test);
}
首先你要保证theInputFile已经开辟了空间,
其次你要保证theInputFile的使用范围在临时变量的作用域之内(这点是不大可能的)!
访问0X0000005错误
我开始也是这样想的,(我以前一直这样想)
函数中char *p='sss';的p指向临时的栈地址,所以我一直用
static char *p="sss";
但我用汇编看了一下,test是在栈上,但它指向的是data段的内容
如下程序:
#include <stdio.h>char *m;
test()
{
char *test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
m=test;
}
main()
{
test();
printf("m=%s\n",m);
}
生成的汇编:
TITLE t.cpp
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC ?m@@3PADA ; m
_BSS SEGMENT
?m@@3PADA DD 01H DUP (?) ; m
_BSS ENDS
PUBLIC ?test@@YAHXZ ; test
_DATA SEGMENT
$SG579 DB 'E:\work\computer\source code\mycode_C++\WTL\MyOopic\inpu'
DB 't\default.inp', 00H
_DATA ENDS
_TEXT SEGMENT
_test$ = -4
?test@@YAHXZ PROC NEAR ; test
; File t.cpp
; Line 5
push ebp
mov ebp, esp
push ecx
; Line 6
mov DWORD PTR _test$[ebp], OFFSET FLAT:$SG579
; Line 7
mov eax, DWORD PTR _test$[ebp]
mov DWORD PTR ?m@@3PADA, eax ; m
; Line 8
leave
ret 0
?test@@YAHXZ ENDP ; test
_TEXT ENDS
PUBLIC _main
EXTRN _printf:NEAR
_DATA SEGMENT
ORG $+2
$SG582 DB 'm=%s', 0aH, 00H
_DATA ENDS
_TEXT SEGMENT
_main PROC NEAR
; Line 10
push ebp
mov ebp, esp
; Line 11
call ?test@@YAHXZ ; test
; Line 12
push DWORD PTR ?m@@3PADA ; m
push OFFSET FLAT:$SG582
call _printf
pop ecx
pop ecx
; Line 13
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
------------------------------------------------------
也可能是以前记错了,也可能是VC编译器对字符串常量优化了
我在cl命令行方式,没问题(VC6+win2k)
-----------------------------------
最好是不要这样写(test[0]='s';)
一语惊醒梦中人!我知道为什么了!
在我的实例程序里面,采用
theGlobalVars.theInputFile = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
来给theGlobalVars.theInputFile赋值,所以没有出问题。而在我实际的程序里面,用的是下面的方法:
______________________________________________________________
LPCTSTR lpcstrFilter =
_T("MyOopic Input Files (*.inp)\0*.inp\0")
_T("All Files (*.*)\0*.*\0")
_T("");
CModulePath sCurDir;
CString sPath = sCurDir + _T("..\\input"); //
// Open file
CFileDialog dlg(TRUE, _T("inp"), _T(""), OFN_EXPLORER | OFN_HIDEREADONLY, lpcstrFilter);
dlg.m_ofn.lpstrInitialDir = sPath;
if( dlg.DoModal() == IDOK ) {
// Open file and read text...
theGlobalVars.theInputFile = dlg.m_ofn.lpstrFile; //语句1:这里是错误的根源!!
m_SolutionView.m_viewMenuTree.populateTree();
}
_______________________________________________________
我把“语句1”改成:
theGlobalVars.theInputFile = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
就一切正常了!!!看来文昌鱼还真是高手!谢谢了!
______________________________________________________
void Ctemp4Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
char* test = new char[256];
CButton* pBtn = (CButton*)GetDlgItem(IDC_BUTTON1);
int iLen = pBtn->GetWindowTextLength();
pBtn->GetWindowText(test,iLen+1 );
theGlobalVars.theInputFile = test;
}
______________________________________________________
我的字符串存放在test这个局部变量里面,它的作用域比theGlobalVars的作用域低,“这个变量的作用域比全局变量低”,那么为什么又对了呢?
__________________________________________________________
LRESULT CMainFrame::OnFileLoadinputfile(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// TODO: 在此添加命令处理程序代码 LPCTSTR lpcstrFilter =
_T("MyOopic Input Files (*.inp)\0*.inp\0")
_T("All Files (*.*)\0*.*\0")
_T("");
CModulePath sCurDir;
CString sPath = sCurDir + _T("..\\input");
// Open file
CFileDialog dlg(TRUE, _T("inp"), _T(""), OFN_EXPLORER | OFN_HIDEREADONLY, lpcstrFilter);
dlg.m_ofn.lpstrInitialDir = sPath;
if( dlg.DoModal() == IDOK ) {
// Open file and read text...
//theGlobalVars.theInputFile = dlg.m_ofn.lpstrFile;
char* test = new char[256];
test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
theGlobalVars.theInputFile = test;
m_SolutionView.m_viewMenuTree.populateTree();
}
return 0;
}
______________________________________________________
看样子,问题出在
theGlobalVars.theInputFile = dlg.m_ofn.lpstrFile;
上
{
// TODO: 在此添加控件通知处理程序代码
char* test = new char[256];
CButton* pBtn = (CButton*)GetDlgItem(IDC_BUTTON1);
int iLen = pBtn->GetWindowTextLength();
pBtn->GetWindowText(test,iLen+1 );
theGlobalVars.theInputFile = test;
}
因为test指向的内存是NEW出来的,如果你没有把他delete掉,他就一直存在