user-0 提问: 函数调用时调用的变量的内存地址变了，造成无法访问内存单元

回复:
user: user-1
content: 理解和讨论之前请先学会如何观察！

user: user-1
content: 谁莫名其妙地改变，就在谁身上设置数据内容改变断点。 然后重新执行或循环执行，调试器会帮你停在改变你之前指定数据的语句或对应汇编指令处。  http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程  工欲善其事，必先利其器。

user: user-1
content: 学会使用数据断点！

user: user-1
content: 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; }

user: user-0
content: 中间有好多行的程序都是读取业务相关的数据，应该没什么用，程序整体编译可以通过。

user: user-0
content: #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; }

user: user-0
content: 引用 8 楼 cyfcsd 的回复:[quote=引用 6 楼 ss053711452 的回复:] [quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] G0如果是在栈上分配的，确实有可能是所占空间太大了，可以考虑移动到堆上，或者改变一下你程序的数据结构，一次用非常多内存，八成是程序设计有缺陷[/quote]  之前用G0保存的数据量比较小，程序没有发生段错误，后来需要读取的数据变多了，我把结构体中的数组维度调大之后就段错误了。我把程序源代码放在楼下了，麻烦您帮我看一下是不是所占空间太大导致的

user: user-2
content: 引用 6 楼 ss053711452 的回复:[quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] G0如果是在栈上分配的，确实有可能是所占空间太大了，可以考虑移动到堆上，或者改变一下你程序的数据结构，一次用非常多内存，八成是程序设计有缺陷

user: user-0
content: 引用 4 楼 zhao4zhong1 的回复:学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化，马上停住程序。有下面的几种方法来设置观察点： watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时，马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时，停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时，停住程序。 info watchpoints 列出当前设置的所有观察点。  我知道程序是在调用CreatSpanningTree()函数的时候出现的段错误，在调用函数的前一条语句时，变量的地址还都对，那么我用watch观察能够进一步找到地址是在哪里发生突变的么

user: user-0
content: 引用 2 楼 cyfcsd 的回复:这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？

user: user-0
content: 引用 4 楼 zhao4zhong1 的回复:学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化，马上停住程序。有下面的几种方法来设置观察点： watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时，马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时，停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时，停住程序。 info watchpoints 列出当前设置的所有观察点。  老师，我修改了一下结构体中数组的最大维度，段错误就发生在调用另外一个函数的时候，感觉段错误只发生在调用函数的时候，此时变量地址发生莫名其妙的被改变了

user: user-0
content: 给出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);                                                                          		                                                                                                                 }

user: user-0
content: 引用 3 楼 cfjtaishan 的回复:段错误，内存非法访问，最好贴出你的代码；  麻烦兄弟帮忙看一下程序呗，我放在9楼了，有点长，程序中间的一些代码行时读取业务相关的数据，应该没有什么影响，麻烦啦  引用 13 楼 cfjtaishan 的回复:[quote=引用 6 楼 ss053711452 的回复:] [quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] 因为传递的是地址，对于CreatSpanningTree()函数，形参只是占4个字节；本身G变量占用栈空间确实挺大的，根据需要来申请空间吧。内存非法访问的地方还需要继续查CreatSpanningTree()函数里的问题。[/quote]  如何根据需要申请空间呢，我G0的结构体是用typedef struct{}定义的，那么理论上G0能使用多大的内存空间呢

user: user-3
content: 引用 6 楼 ss053711452 的回复:[quote=引用 2 楼 cyfcsd 的回复:] 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码  源代码有点长，我整理整理的；先问一句，有没有可能是变量G0这个地址保存的结构体太大了，使得CreatSpanningTree()函数调用的时候没有足够大的内存保存数据，如果是怎么处理，把*G0分两个结构体保存？[/quote] 因为传递的是地址，对于CreatSpanningTree()函数，形参只是占4个字节；本身G变量占用栈空间确实挺大的，根据需要来申请空间吧。内存非法访问的地方还需要继续查CreatSpanningTree()函数里的问题。

user: user-4
content: 内存非法访问

user: user-1
content: 学会使用数据断点。 2. 设置观察点(WatchPoint) 观察点一般用来观察某个表达式(变量也是一种表达式)的值是否变化了。如果有变化，马上停住程序。有下面的几种方法来设置观察点： watch <expr> 为表达式(变量)expr设置一个观察点。一旦表达式值有变化时，马上停住程序。 rwatch <expr> 当表达式(变量)expr被读时，停住程序。 awatch <expr> 当表达式(变量)的值被读或被写时，停住程序。 info watchpoints 列出当前设置的所有观察点。

user: user-3
content: 段错误，内存非法访问，最好贴出你的代码；

user: user-2
content: 这个段错误，是你访问的内存越界了，是不是分配的内存少了啊，最好贴出相关源代码

user: user-0
content: 这个问题困扰自己好久了，什么原因啊啊啊啊啊啊啊啊 我是在Linux环境下，用GDB跟踪调试的