[완료]C code - free만 쓰면. 코드가 터집니다.. 어떤점이 문제인가요?

KD K@Google의 이미지

안녕하세요
알고리즘 공부중입니다.

입력받은 파일을 linkList로 만든후
DFS로 Topological Sort 를 생성.
longest path를 찾는 문제입니다.
알고리즘 상 문제는 없어보이는데..

문제는 main 함수 마지막에 free를 쓰면 값은 모두출력되는데
출력후 프로그램이 정지합니다.
free를 안쓰면 잘돌아가구요.

free쓰는것에 뭐가 문제가 있나요?
그리고.

아무리 봐도 제 코드가 지저분해 보이는데
코드를 깔끔하게 짜는데 참고할만한 것있으면[책이라던가.. 사이트라던가].. 조언부탁드립니다.

#include<stdio.h>
#include<stdlib.h>
#define WHITE 0
#define GRAY -1
#define BLACK 1
 
typedef struct element *eleptr;
typedef struct element
{
	int extend;
	int height;
	int weight;
}element;
typedef struct node *nodeptr;
typedef struct node
{
	int to;
	int w;
	nodeptr link;
}node;
int edgeNum;
 
 
nodeptr tp_header = NULL;
element *inArr =NULL;
nodeptr *listhead =NULL;
 
 
/////////////dfs//////////
int * p = NULL;
int * d = NULL;
int * color = NULL;
int p2[50];
int d2[50];
void dfs_visit(int u);
void dfs();
 
//////////////////
 
nodeptr mknode(int to, int w);
void inputdata();
void mkList();
void printfList();
void DSP();
void relax(int u,int v);
 
int main(void)
{
	int i;
	p=(int*)malloc(sizeof(int)*(edgeNum+2));
	color=(int*)malloc(sizeof(int)*(edgeNum+2));
	d=(int*)malloc(sizeof(int)*(edgeNum+2));
 
	inputdata();
	mkList();
	printfList();
	dfs();
 
	DSP();
	for(i=0;i<edgeNum+2;i++)
	{
		printf("  %d",d2[i]);
	}
	printf("\n");
 
	for(i=0;i<edgeNum+2;i++)
	{
		printf("  %d",p2[i]);
	}
	printf("\n");
	for(i=edgeNum+1;i!=0;i=p2[i])
	{
		printf("  %d",p2[i]);
	}
	printf("\n");
	printf("  %d\n",d2[edgeNum+1]);
 
	free(p);
	free(color);
	free(d);
	free(listhead);
	free(inArr);
 
	return 0;
}
nodeptr mknode(int to, int w)
{
	nodeptr tmp;
	tmp = (nodeptr)malloc(sizeof(node));
	tmp->to=to;
	tmp->w=w;
	tmp->link=NULL;
	return tmp;
}
 
void inputdata()
{
	FILE *fp_input;
	char file_name[30];	
	int i,j;
 
	printf("input ifle name?");
	scanf("%s",file_name);
	fp_input = fopen(file_name,"r");
 
	if(fp_input == NULL)
	{
		fprintf(stderr,"FILE <%s> open error.\n",file_name);
		exit(1);
	}
	fscanf(fp_input,"%d",&edgeNum);
	inArr = (eleptr)malloc(sizeof(element)*(edgeNum+3));
	inArr[0].extend=9999;
	inArr[0].height=0;
	inArr[0].weight=9999;
 
	for(i=1;i<=edgeNum;i++)
	{
		fscanf(fp_input,"%d %d %d",&(inArr[i].extend),&(inArr[i].height),&(inArr[i].weight));
	}
	inArr[edgeNum+1].extend=0;
	inArr[edgeNum+1].height=0;
	inArr[edgeNum+1].weight=0;
}
 
void mkList()
{
	int i,j	;
	nodeptr tmp;
 
 
	listhead = (nodeptr*)malloc(sizeof(nodeptr)*(edgeNum+2));
 
	for(i=0;i<edgeNum+2;i++)
		listhead[i]=NULL;
 
	for(i=0;i<=edgeNum+1;i++)
	{
		for(j=i;j<=edgeNum+1;j++)
		{
			if(inArr[i].extend <inArr[j].extend && inArr[i].weight < inArr[j].weight)
			{// i 의 돌이 j 의 돌보다 작고 가벼우면 j->i 로 연결
				tmp=mknode(i,inArr[j].height);
				if(listhead[j]==NULL)
				{
					listhead[j]=tmp;
				}
				else
				{
					tmp->link=listhead[j];
					listhead[j]=tmp;
				}
			}
			else if(inArr[i].extend >inArr[j].extend && inArr[i].weight > inArr[j].weight)
			{
				tmp=mknode(j,inArr[i].height);
				if(listhead[i]==NULL)
				{
					listhead[i]=tmp;
				}
				else
				{
					tmp->link=listhead[i];
					listhead[i]=tmp;
				}
			}
		}
	}
}
 
void printfList()
{
	int i;
	nodeptr temp=NULL;
 
	for(i=0;i<edgeNum+2;i++)
	{		
		temp=listhead[i];
		printf("from%2d =>",i);
		while(temp!=NULL)
		{
			printf("[to=%2d h=%2d] -->",temp->to,temp->w);
			temp=temp->link;
		}
		printf(" X");
		printf("\n");
	}
}
 
void DSP()
{
	int i;
	nodeptr temp;
	nodeptr temp2;
 
	for(i=0;i<edgeNum+2;i++)
	{
		d2[i]=0;
		p2[i]=NULL;
	}
	d2[0]=0;	
 
	temp=tp_header;
	while(temp!=NULL)
	{
		temp2=listhead[temp->to];
		while(temp2!=NULL)
		{
			relax(temp->to,temp2->to);
			temp2=temp2->link;
		}
		temp=temp->link;
	}		
}
 
void relax(int u,int v)
{
	if(d2[v] < d2[u] + inArr[u].height)
	{
		d2[v] = d2[u] +inArr[u].height;
		p2[v] = u;
	}	
}
 
void dfs()
{
	int i,j;	
	nodeptr temp;
 
	for(i=0;i<edgeNum+2;i++)
	{
		p[i]=-1;
		color[i]=WHITE;
	}
	for(i=0;i<edgeNum+2;i++)
	{
		if(color[i]==WHITE)
		{
			dfs_visit(i);		
		}
	}
 
	printf("TP\n");
	temp=tp_header;
	while(temp!=NULL)
	{
		printf("%3d",temp->to);
		temp=temp->link;
	}
	printf("\n");
}
 
void dfs_visit(int u)
{
	nodeptr temp;
	nodeptr cur = listhead[u];
	color[u] =GRAY;
	while(cur)
	{
		if(color[cur->to]==WHITE)
		{
			p[cur->to] = u;
			dfs_visit(cur->to);
		}
		cur = cur->link;
	}
	color[u]=BLACK;
	temp=mknode(u,0);	
	temp->link=tp_header;
	tp_header=temp;	
}
 
<code>
input
5
25 3 4
4 4 6
9 2 3
16 2 5
1 5 2

 의 이미지

free에서 런타임 에러가 발생한다는 건 보통 힙이 깨졌다는 걸 의미합니다.
주어진 코드와 같이 힙에 가변 길이 자료구조를 올려놓고 접근하는 경우, 주의하지 않으면 할당된 범위 밖을 접근하면서 힙을 깨트릴 가능성이 매우 높습니다.
문제는, 힙이 깨진 즉시 에러가 나는 게 아니라 잘 도는 것처럼 보이다가 나중에 터진다는 거죠. 설령 눈에 띄는 에러가 발생하지 않는다고 해도 프로그램이 정상적으로 동작한다는 보장도 없고요. 복불복이죠.

문제가 여럿 있을 수 있지만 일단 가장 눈에 띄는 것 하나 먼저 지적하지요.

main함수는 시작하자마자 아래와 같은 코드로 동적 배열을 할당하는데,

	p=(int*)malloc(sizeof(int)*(edgeNum+2));
	color=(int*)malloc(sizeof(int)*(edgeNum+2));
	d=(int*)malloc(sizeof(int)*(edgeNum+2));

그 시점에서는 아직 사용자 입력을 읽지 않았기 때문에(inputdata) 전역 변수 edgeNum의 값은 0입니다. 터무니없이 작은 배열을 할당한 것이지요.
이후 사용자 입력을 받아 edgeNum에 0보다 큰 값이 들어가면 dfs나 dfs_visit 등의 함수들은 할당받은 배열 밖에 값을 읽고 쓰고 합니다. 그 결과 힙이 개판이 되고 나중에 free할 때 프로그램이 깨지는 겁니다.

KD K@Google의 이미지

아! 답변 감사합니다. 그러네요. input을 받기전에 먼저 malloc을 먼저 하는군요 정말 답변 감사합니다.
그부분을 해결하면 깔끔하게 돌아가네요.!!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.