函数调用时调用的变量的内存地址变了,造成无法访问内存单元

ss053711452 2017-02-28 04:41:01
如题如图,当我调用CreatSpanningTree()函数时,提示无法访问所示内存地址,而且这个地址和我调用函数前的G0地址不一样啊,为什么会出现这种内存地址变了的情况啊,求助各位大神给分析分析!!!
另外,G0保存的是一个大结构体,我发现当G0中的数据量不是很大的时候,调用函数可以成功;当G0中保存的数据过多时,发生了上述地址改变无法访问的情况,不明所以。。。。

...全文
637 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2017-03-02
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察
赵4老师 2017-03-02
  • 打赏
  • 举报
回复
谁莫名其妙地改变,就在谁身上设置数据内容改变断点。 然后重新执行或循环执行,调试器会帮你停在改变你之前指定数据的语句或对应汇编指令处。 http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程 工欲善其事,必先利其器。
赵4老师 2017-03-02
  • 打赏
  • 举报
回复
学会使用数据断点!
赵4老师 2017-03-01
  • 打赏
  • 举报
回复
Windows下数据断点参考:
#include <time.h>
#include <stdlib.h>
#include <windows.h>
int main() {
    int a,b[11];//本来是b[10],为判断哪句越界,故意声明为b[11]

    srand((unsigned int)time(NULL));//按两次F11,等黄色右箭头指向本行时,调试、新建断点、新建数据断点,地址:&b[10],字节计数:4,确定。
    while (1) {//按F5,会停在下面某句,此时a的值为10,b[10]已经被修改为对应0..4之一。
        b[(a=rand()%11)]=0;
        Sleep(100);
        b[(a=rand()%11)]=1;
        Sleep(100);
        b[(a=rand()%11)]=2;
        Sleep(100);
        b[(a=rand()%11)]=3;
        Sleep(100);
        b[(a=rand()%11)]=4;
        Sleep(100);
    }
    return 0;
}
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
中间有好多行的程序都是读取业务相关的数据,应该没什么用,程序整体编译可以通过。
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
#define MAXV 500 #define VERTEX_MAX 800 #define MAXVALUE 32767 #define MAX_VERTAX_NUM 500 #define QUEUE_MAXSIZE 600 #define charLen 20 typedef struct { int Vertex[VERTEX_MAX]; double Edges[VERTEX_MAX][VERTEX_MAX]; int isMainLink[VERTEX_MAX][VERTEX_MAX]; int isTrav[VERTEX_MAX]; int VertexNum; int EdgeNum; int GraphType; int isTwoEdges[VERTEX_MAX][VERTEX_MAX]; }MatrixGraph; typedef struct Station{ char id[255]; char name[255]; char v[255]; struct Station *next; }Station; int rx_check(char *dv_name) { int ret, i, j; MatrixGraph G; struct Station *nSP,*Sp1,*SHead; nSP = (struct Station*)malloc(sizeof(struct Station)); stationList=nSP; SHead=nSP; Sp1=nSP; setstationCount() ; struct Line *nLP,*Lp1,*Lhead; nLP = (struct Line*)malloc(sizeof(struct Line)); lineList=nLP; Lhead=nLP; Lp1=nLP; setLineCount(); for(i=0;i<lv_st_mod;i++) { float kvvl = 0.0; //最高电压等级 int hkv = -1; if(hkv <0) continue; float st_v = 0.0; //找最大电压等级的母线 if((hkv > -1)&&(kv_mod[hkv].oo_kv_bus_fa > 0)) { int _bptr = kv_mod[hkv].oo_kv_bus_fa; do{ int _bus = oo_r_kv_bus_mod[_bptr].ichild; //bus_mod.v_pre:母线电压量测值,v:电压估计值 if(bus_mod[_bus].v_pre >= st_v) { st_v = bus_mod[_bus].v_pre; } _bptr=oo_r_kv_bus_mod[_bptr].bptr; }while(_bptr > -1); } if(st_v < 1.0 )//还有最高电压等级没有母线建模的厂站,added by sxr { st_v = bs_mod[kv_mod[hkv].ibs].v * kv_mod[hkv].nomvol; } //山东线路两端的厂站 if(st_mod[i].ibsl == 2) //不等于2就不定级了? { int st_class = 0; if(kvvl >= 500) {st_class = 2;} else if((kvvl < 500)&&(kvvl > 200)) { st_class = 3; } else { continue; } int _st_x=-1; int _st_y=-1; /* ret = find_st_xy(st_mod[i].name); if(ret > -1) { _st_x = st_xy[ret].st_x; _st_y = st_xy[ret].st_y; } */ char _id[255]; sprintf(_id,"%ld",st_mod[i].id); char _v[255]; sprintf(_v,"%.1f", st_v); //============================================================================================ stationList=insert_StationList(stationList,_id,st_mod[i].name,_v); stationCount++; //end printf("<station_data id=\"%d\" name=\"%s\" v=\"%.1f\"/>\n", st_mod[i].id, st_mod[i].name, st_v); st_mod[i].ibsl = 1; } } Station *LHead3=stationList; for(i=0;i<lv_ln_mod;i++) { int ist, zst; ist = kv_mod[ln_mod[i].ikv].ist; zst = kv_mod[ln_mod[i].zkv].ist; if(ist == zst) continue; int kv_type = find_kvvl(kv_mod[ln_mod[i].ikv].vl); int ln_class = 0; if(kv_mod[ln_mod[i].ikv].vl >= 500) {ln_class = 2;} else if(kv_mod[ln_mod[i].ikv].vl >= 200 && kv_mod[ln_mod[i].ikv].vl < 300) {ln_class = 3;} else {continue;} int _st_xi=-1; int _st_yi=-1; int _st_xj=-1; int _st_yj=-1; if(ln_mod[i].iisland0 == 1) { char _id[255]; sprintf(_id,"%ld",ln_mod[i].id); char i_id[255]; sprintf(i_id,"%ld",st_mod[ist].id); char j_id[255]; sprintf(j_id,"%ld",st_mod[zst].id); char vtype[255]; sprintf(vtype,"%d",kv_type); char _class[255]; sprintf(_class,"%d",ln_class); char _pi[255]; sprintf(_pi,"%.1f",ln_mod[i].pi_pre); char _pz[255]; sprintf(_pz,"%.1f",ln_mod[i].pz_pre); char _x[255]; sprintf(_x,"%f",ln_mod[i].x); lineList=insert_LineList(lineList,_id,i_id,j_id,ln_mod[i].name,vtype,_class,_pi,_pz,_x); LineCount++; } } //GJ---------构造邻接矩阵-----------// int staCount=getstationCount(); G.VertexNum=staCount; G.EdgeNum =getLineCount(); //边赋值 Line *nP3 =lineList; int linecount,dLineCount; double delt_p = 0.0f; do{ int stri_id=atoi(nP3->sti_id); int strj_id=atoi(nP3->stj_id); char* pi=nP3->pi; if(strcmp(pi,"0.0") ) { for(i=0;i<staCount;i++) { for(j=0;j<staCount;j++) { //if(strcmp(G.Vertex[i],stri_id)==0 && strcmp(G.Vertex[j],strj_id)==0) if((G.Vertex[i]==stri_id)&&(G.Vertex[j]==strj_id)) { if(G.Edges[i][j]== MAXVALUE) { //G.Edges[i][j]=1; //G.Edges[j][i]=1; delt_p = fabs(atof(nP3->pi)+atof(nP3->pz)); if(delt_p < 0.01) { G.Edges[j][i]=0.01; G.Edges[i][j]=0.01; } else { G.Edges[j][i]=delt_p; G.Edges[i][j]=delt_p; } } else { G.isTwoEdges[i][j]=1; G.isTwoEdges[j][i]=1; dLineCount++; } linecount++;//linecount? } } } } nP3=nP3->next; }while(nP3!=Lhead ); //因为边的信息是反着排的 printf("LineCount is %d, dLineCount is %d. \n",linecount,dLineCount); dyn_string_t m_LoopCircleStr=dyn_string_new(0); CreateSpanningTree(&G,m_LoopCircleStr); printf("环有:%s\n",m_LoopCircleStr->s); //以先路id形式表示各个环路 //===============================================================================================后面还有很多行,省略了…… //end---------------// free(nSP); free(nLP); free(loopHead); free(loopTail); nSP = NULL; nLP = NULL; loopHead = NULL; loopTail = NULL; return 1; }
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
引用 8 楼 cyfcsd 的回复:
[quote=引用 6 楼 ss053711452 的回复:] [quote=引用 2 楼 cyfcsd 的回复:] 这个段错误,是你访问的内存越界了,是不是分配的内存少了啊,最好贴出相关源代码
源代码有点长,我整理整理的;先问一句,有没有可能是变量G0这个地址保存的结构体太大了,使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据,如果是怎么处理,把*G0分两个结构体保存?[/quote] G0如果是在栈上分配的,确实有可能是所占空间太大了,可以考虑移动到堆上,或者改变一下你程序的数据结构,一次用非常多内存,八成是程序设计有缺陷[/quote] 之前用G0保存的数据量比较小,程序没有发生段错误,后来需要读取的数据变多了,我把结构体中的数组维度调大之后就段错误了。我把程序源代码放在楼下了,麻烦您帮我看一下是不是所占空间太大导致的
flying_music 2017-03-01
  • 打赏
  • 举报
回复
引用 6 楼 ss053711452 的回复:
[quote=引用 2 楼 cyfcsd 的回复:] 这个段错误,是你访问的内存越界了,是不是分配的内存少了啊,最好贴出相关源代码
源代码有点长,我整理整理的;先问一句,有没有可能是变量G0这个地址保存的结构体太大了,使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据,如果是怎么处理,把*G0分两个结构体保存?[/quote] G0如果是在栈上分配的,确实有可能是所占空间太大了,可以考虑移动到堆上,或者改变一下你程序的数据结构,一次用非常多内存,八成是程序设计有缺陷
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
引用 4 楼 zhao4zhong1 的回复:
学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化,马上停住程序。有下面的几种方法来设置观察点: watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时,马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时,停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时,停住程序。 info watchpoints 列出当前设置的所有观察点。
我知道程序是在调用CreatSpanningTree()函数的时候出现的段错误,在调用函数的前一条语句时,变量的地址还都对,那么我用watch观察能够进一步找到地址是在哪里发生突变的么
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
引用 2 楼 cyfcsd 的回复:
这个段错误,是你访问的内存越界了,是不是分配的内存少了啊,最好贴出相关源代码
源代码有点长,我整理整理的;先问一句,有没有可能是变量G0这个地址保存的结构体太大了,使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据,如果是怎么处理,把*G0分两个结构体保存?
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
引用 4 楼 zhao4zhong1 的回复:
学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化,马上停住程序。有下面的几种方法来设置观察点: watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时,马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时,停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时,停住程序。 info watchpoints 列出当前设置的所有观察点。
老师,我修改了一下结构体中数组的最大维度,段错误就发生在调用另外一个函数的时候,感觉段错误只发生在调用函数的时候,此时变量地址发生莫名其妙的被改变了
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
给出CreateSpanningTree() 函数形式,求大神帮我看看这里有没有什么问题 //生成树 void CreateSpanningTree(MatrixGraph *G,dyn_string_t m_LoopCircleStr) { int i,j; for(i=0;i<G->VertexNum;i++) { G->isTrav[i] =0; } //printf("生成树的节点和边:\n"); printf("按广度优先遍历节点顺序:\n"); for(i=0;i<G->VertexNum;i++) { if(!G->isTrav[i]) CBFSM(G,i); } printf("\n"); //构造生成树图 MatrixGraph TreeG; TreeG.VertexNum = G->VertexNum; TreeG.EdgeNum=G->EdgeNum; //printf("构造生成树\n"); //顶点赋值 for(i=0;i<G->VertexNum;i++) { TreeG.Vertex[i] = G->Vertex[i]; } //初始化 for(i=0;i<G->VertexNum;i++) { for(j=0;j<G->VertexNum;j++) { TreeG.Edges[i][j]=MAXVALUE; TreeG.isMainLink[i][j]=0; if(G->isMainLink[i][j]==1 && G->Edges[i][j] != MAXVALUE) { TreeG.Edges[i][j]=G->Edges[i][j]; TreeG.isMainLink[i][j]=1; TreeG.Edges[j][i]=G->Edges[j][i]; TreeG.isMainLink[j][i]=1; } } } //printf("输出原始生成树:\n"); printf("广度优先遍历邻接矩阵:\n"); Outlin(&TreeG); //输出邻接矩阵 //=============================================================================================== //Outlin(G); //寻找最小闭合环 FindClosedLoop(G,&TreeG,m_LoopCircleStr); }
ss053711452 2017-03-01
  • 打赏
  • 举报
回复
引用 3 楼 cfjtaishan 的回复:
段错误,内存非法访问,最好贴出你的代码;
麻烦兄弟帮忙看一下程序呗,我放在9楼了,有点长,程序中间的一些代码行时读取业务相关的数据,应该没有什么影响,麻烦啦
引用 13 楼 cfjtaishan 的回复:
[quote=引用 6 楼 ss053711452 的回复:] [quote=引用 2 楼 cyfcsd 的回复:] 这个段错误,是你访问的内存越界了,是不是分配的内存少了啊,最好贴出相关源代码
源代码有点长,我整理整理的;先问一句,有没有可能是变量G0这个地址保存的结构体太大了,使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据,如果是怎么处理,把*G0分两个结构体保存?[/quote] 因为传递的是地址,对于CreatSpanningTree()函数,形参只是占4个字节;本身G变量占用栈空间确实挺大的,根据需要来申请空间吧。内存非法访问的地方还需要继续查CreatSpanningTree()函数里的问题。[/quote] 如何根据需要申请空间呢,我G0的结构体是用typedef struct{}定义的,那么理论上G0能使用多大的内存空间呢
自信男孩 2017-03-01
  • 打赏
  • 举报
回复
引用 6 楼 ss053711452 的回复:
[quote=引用 2 楼 cyfcsd 的回复:] 这个段错误,是你访问的内存越界了,是不是分配的内存少了啊,最好贴出相关源代码
源代码有点长,我整理整理的;先问一句,有没有可能是变量G0这个地址保存的结构体太大了,使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据,如果是怎么处理,把*G0分两个结构体保存?[/quote] 因为传递的是地址,对于CreatSpanningTree()函数,形参只是占4个字节;本身G变量占用栈空间确实挺大的,根据需要来申请空间吧。内存非法访问的地方还需要继续查CreatSpanningTree()函数里的问题。
Rookiekk 2017-02-28
  • 打赏
  • 举报
回复
内存非法访问
赵4老师 2017-02-28
  • 打赏
  • 举报
回复
学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化,马上停住程序。有下面的几种方法来设置观察点: watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时,马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时,停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时,停住程序。 info watchpoints 列出当前设置的所有观察点。
自信男孩 2017-02-28
  • 打赏
  • 举报
回复
段错误,内存非法访问,最好贴出你的代码;
flying_music 2017-02-28
  • 打赏
  • 举报
回复
这个段错误,是你访问的内存越界了,是不是分配的内存少了啊,最好贴出相关源代码
ss053711452 2017-02-28
  • 打赏
  • 举报
回复
这个问题困扰自己好久了,什么原因啊啊啊啊啊啊啊啊 我是在Linux环境下,用GDB跟踪调试的

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧