我写了一个windows的程序,其中用到了全局变量,我将它单独放到了一个类里面,是这么定义的:
char* theFileName;
然后在外部文件里面定义为extern型的变量。当程序第一次给theFileName赋值的时候,一切正常,查看地址是0x0012f060,里面的内容也是正常的:“E:\computer\source code\mycode_C++\WTL\input\default.inp”;
但是,当程序在另外一个类里面又要取这个值的时候,地址还是0x0012f060,但里面的内容却变成了“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”这是为什么呢?
-------------------------------------------------
<hr>
另外,我又写了一个最简单的MFC程序,同样是有一个全局变量,同样是在一个类里面给全局变量赋值,在另外一个类里面取值,却一点错误都没有,究竟是为什么呢?有什么窍门?

解决方案 »

  1.   

    theFileName = new char[128];
    是否是这样开辟一个空间赋值给theFileName ,然后再对theFileName指向得地址填充字符串呢?如果是这样得话,肯定不会有问题!但是如果你只是把theFileName 指向一个局部得变量得地址,那么一旦超出得局部变量的作用域局部变量内容可能就没了!可能就会出现你的问题!
      

  2.   

    关键在那个类上, 楼主将全局变量不要放在类里, 或者放在一个拥有全局唯一实例的类里, 就象 MFC 的 theApp 那样的类, 如果是一个普通的类,关没有定义为全局变量,那么它不能用来保持一个全局值
      

  3.   

    定义在类里面的还是全局变量吗?
    那是类的成员变量。
    如果非要放在类里,改成Static类型
      

  4.   

    你的全局变量只是一个指针,四个字节,指针指向的内容并不是全局的。所以你在别的类里用指针就会出错。至于有时正确有时出错,那和指针指向的变量的作用域有关系。
    按照你的意思。应该用前面  handwolf(青松崖) 提到的方法,在堆中分配内存,
    char * theFileName = new char[128];
    或者直接把指针改为 char theFileName[128];这样全局区会分配128个字节的空间。可以直接用theFileName 指向这个字符串。
      

  5.   

    我的全局变量类是这样定义的:
    #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;
    ___________________________________________________________________
    看了前面的留言,似乎觉得这样是有问题的。
    但是,如果我有很多个全局变量,但是又想以很好的方式把它组织起来,应该用什么方法比较好呢?
      

  6.   

    但是,我建立了一个最简单的对话框程序,思路一样,运行却完全正常啊:
    ***********************************************************************
    #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);
    }
    ***********************************************************************
      

  7.   

    char* test = new char[256];
    test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
    theGlobalVars.theInputFile = test;
    ===========================================================
    已经分配空间了,是不会出错的。你原来的windows程序的代码是什么样的??
      

  8.   

    char* test = new char[256];             //这里已经分配内存了:
    test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp"; //test重新赋值 ,指针已改变
    theGlobalVars.theInputFile = test;
    且test没有释放
      

  9.   

    不要这样赋值test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
    你可以用strcpy,或者memcpy
      

  10.   

    如下写:
    char* test = new char[256];strcpy( test , "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp" );
      

  11.   

    char* test = new char[256];
    test = "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
    的代码都写的出来,不知道你的C++是怎么学的
      

  12.   

    各位高手,问题的关键不在这里,我都说过了,这样的写法:
    【 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++又是怎么学的呢?能否解释我这里全部变量的问题?
      

  13.   

    你这样写:"E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
    这些数据是存在栈中的
    函数执行完后,栈里的数据就没有了
      

  14.   

    To  kuangjingbo(正在学习windows) 
    我给出了代码的示例程序,运行结果是完全正确的啊
      

  15.   

    "E:\\work\\computer\\source code\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";是全局的字符常量,不应在栈中.
    如:
    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所指的数据区破坏了
      

  16.   

    如果说你的程序也是这样赋值的
    theGlobalVars.theInputFile="E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
    我可以保证绝对没问题,因为"E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp"这个是放在代码段中,除非程序结束,要不然就不会被摧毁
      

  17.   

    可以考虑把那个类声明为 static
      

  18.   

    给你分析一下下面的代码:char* test = new char[256];//test指向新开辟的堆地址(比如0x003c0a28)
    test = "E:\\";//test指向临时的栈地址(比如0x0046e020)
    theGlobalVars.theInputFile = test;//此时把临时的栈地址赋给了theInputFile 
    test = NULL;//这个是没关系的,只是把指针指向空!但是你要记得释放开辟的堆空间!上面的代码结束后,象我在前面说的一样,可能跳出了栈地址(比如0x003c0a28)的作用域,这样0x003c0a28中的内容就不会保留下来,所以出现了“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”楼主明白了没有?要把指针操作和几个内存空间弄清楚(堆和栈等等)
      

  19.   

    to:Lancelet(文昌鱼)
    看我上面的汇编,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);
    }
      

  20.   

    to Lancelet(文昌鱼) :theGlobalVars.theInputFile="E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp"; 这样的赋值是不正确的,容易出问题!
     
    首先你要保证theInputFile已经开辟了空间,
    其次你要保证theInputFile的使用范围在临时变量的作用域之内(这点是不大可能的)!
      

  21.   

    to Lancelet(文昌鱼) :呵呵,sorry,没看清楚,收回上面的发言!下面的语句可以用,但是作用域的限制太大了。theGlobalVars.theInputFile="E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
      

  22.   

    运行到这一句的时候出错了test[0]='s';
    访问0X0000005错误
      

  23.   

    handwolf(青松崖) :
      我开始也是这样想的,(我以前一直这样想)
      函数中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编译器对字符串常量优化了
      

  24.   

    to:Lancelet(文昌鱼) 
     我在cl命令行方式,没问题(VC6+win2k)
    -----------------------------------
    最好是不要这样写(test[0]='s';)
      

  25.   

    的确在windows方式下,test[0]='s'会产生非法操作,我以前也没记错,只是VC在命令行下生成的居然和windwos下的不一样,晕了一把
      

  26.   

    本来以为"E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp"是放在代码段,因为以前我时碰到这个问题,可以读取不能修改,让我以为他在代码段,现在看了汇编知道自己错了,不过他的生命周期因该和全局变量一样吧.
      

  27.   

    楼主指的“E:\computer\source code\mycode_C++\WTL\input\default.inp"这个因该不是常量吧,而是放在一个变量里,但这个变量的作用域比全局变量低.(猜测而已)
      

  28.   

    To Lancelet(文昌鱼) ====Thanks Very Much!!
    一语惊醒梦中人!我知道为什么了!
    在我的实例程序里面,采用
    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";
    就一切正常了!!!看来文昌鱼还真是高手!谢谢了!
      

  29.   

    问题又来了,为什么我在示例程序中这样写却又对了呢?
    ______________________________________________________
    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的作用域低,“这个变量的作用域比全局变量低”,那么为什么又对了呢?
      

  30.   

    我在实际的程序里面写成这样,也不会出问题:
    __________________________________________________________
    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;
      

  31.   

    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指向的内存是NEW出来的,如果你没有把他delete掉,他就一直存在