char指针的内容为什么被改变了?

huawdai 2005-06-06 11:28:07
我写了一个windows的程序,其中用到了全局变量,我将它单独放到了一个类里面,是这么定义的:
char* theFileName;
然后在外部文件里面定义为extern型的变量。

当程序第一次给theFileName赋值的时候,一切正常,查看地址是0x0012f060,里面的内容也是正常的:“E:\computer\source code\mycode_C++\WTL\input\default.inp”;
但是,当程序在另外一个类里面又要取这个值的时候,地址还是0x0012f060,但里面的内容却变成了“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”

这是为什么呢?
-------------------------------------------------
<hr>
另外,我又写了一个最简单的MFC程序,同样是有一个全局变量,同样是在一个类里面给全局变量赋值,在另外一个类里面取值,却一点错误都没有,究竟是为什么呢?有什么窍门?
...全文
361 40 打赏 收藏 举报
写回复
40 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
forover 2005-06-07
出现“烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”这种情况
指针虽然还在,内存却被释放掉了
全局变量不要放到类里面定义,放到类外部定义
  • 打赏
  • 举报
回复
Lancelet 2005-06-07
很简单,原来的那块内存被释放了
  • 打赏
  • 举报
回复
oyljerry 2005-06-07
注意变量的生命期
  • 打赏
  • 举报
回复
RemoK 2005-06-07
你的全局变量只是一个指针,四个字节,指针指向的内容并不是全局的。所以你在别的类里用指针就会出错。至于有时正确有时出错,那和指针指向的变量的作用域有关系。
按照你的意思。应该用前面 handwolf(青松崖) 提到的方法,在堆中分配内存,
char * theFileName = new char[128];
或者直接把指针改为 char theFileName[128];这样全局区会分配128个字节的空间。可以直接用theFileName 指向这个字符串。
  • 打赏
  • 举报
回复
Featured 2005-06-07
定义在类里面的还是全局变量吗?
那是类的成员变量。
如果非要放在类里,改成Static类型
  • 打赏
  • 举报
回复
horisly 2005-06-07
当程序在另外一个类里面又要取这个值的时候,地址还是0x0012f060,
===========
指针本身的地址当然不变拉。
但是,由于开始使用指针时候,你没有给指针分配空间,所以后来指针指向的地址超出作用域了,变成了野指针,自然就乱码拉
  • 打赏
  • 举报
回复
Lancelet 2005-06-07
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掉,他就一直存在
  • 打赏
  • 举报
回复
icansaymyabc 2005-06-07
"其中用到了全局变量,我将它单独放到了一个类里面"????

放到了类里面的东西怎么可能是全局变量?

你把你的 类的申明和 变量的申明都贴出来看看。

  • 打赏
  • 举报
回复
huawdai 2005-06-07
我在实际的程序里面写成这样,也不会出问题:
__________________________________________________________
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;
  • 打赏
  • 举报
回复
huawdai 2005-06-07
问题又来了,为什么我在示例程序中这样写却又对了呢?
______________________________________________________
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的作用域低,“这个变量的作用域比全局变量低”,那么为什么又对了呢?
  • 打赏
  • 举报
回复
huawdai 2005-06-07
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";
就一切正常了!!!

看来文昌鱼还真是高手!谢谢了!
  • 打赏
  • 举报
回复
Lancelet 2005-06-07
楼主指的“E:\computer\source code\mycode_C++\WTL\input\default.inp"这个因该不是常量吧,而是放在一个变量里,但这个变量的作用域比全局变量低.(猜测而已)
  • 打赏
  • 举报
回复
Lancelet 2005-06-07
本来以为"E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp"是放在代码段,因为以前我时碰到这个问题,可以读取不能修改,让我以为他在代码段,现在看了汇编知道自己错了,不过他的生命周期因该和全局变量一样吧.
  • 打赏
  • 举报
回复
柯本 2005-06-07
的确在windows方式下,test[0]='s'会产生非法操作,我以前也没记错,只是VC在命令行下生成的居然和windwos下的不一样,晕了一把
  • 打赏
  • 举报
回复
柯本 2005-06-07
to:Lancelet(文昌鱼)
我在cl命令行方式,没问题(VC6+win2k)
-----------------------------------
最好是不要这样写(test[0]='s';)
  • 打赏
  • 举报
回复
柯本 2005-06-07
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编译器对字符串常量优化了
  • 打赏
  • 举报
回复
Lancelet 2005-06-07
运行到这一句的时候出错了test[0]='s';
访问0X0000005错误
  • 打赏
  • 举报
回复
handwolf 2005-06-07
to Lancelet(文昌鱼) :

呵呵,sorry,没看清楚,收回上面的发言!

下面的语句可以用,但是作用域的限制太大了。

theGlobalVars.theInputFile="E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";
  • 打赏
  • 举报
回复
handwolf 2005-06-07
to Lancelet(文昌鱼) :

theGlobalVars.theInputFile="E:\\work\\computer\\sourcecode\\mycode_C++\\WTL\\MyOopic\\input\\default.inp";

这样的赋值是不正确的,容易出问题!

首先你要保证theInputFile已经开辟了空间,
其次你要保证theInputFile的使用范围在临时变量的作用域之内(这点是不大可能的)!
  • 打赏
  • 举报
回复
柯本 2005-06-07
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);
}
  • 打赏
  • 举报
回复
加载更多回复
相关推荐
发帖
VC/MFC
加入

1.6w+

社区成员

VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
申请成为版主
帖子事件
创建了帖子
2005-06-06 11:28
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……