[초보]C언어 segmentation fault 관련 질문입니다.
학교 과제로 전화번호와 이름을 저장,출력 하는 프로그램을 만드는데
malloc과 구조체 포인터 배열을 이용해서 만들어야 합니다.
#include
#include
#include
typedef struct infomation{
char name[20];
char phone[30];
}info;//이름과 전화번호를 저장할 구조체
int menu()//메뉴 출력 함수
{
printf("*****Menu*****\n");
printf("<1.Registration><2.ShowAll><3.Search>\n");
printf("<4.Deletion><5.Modification><6.Exit>\n");
printf("Enter_the_menu_number:");
return 0;
}
int get_menu_num()//메뉴번호 선택 함수
{
int n;
scanf("%d",&n);
return n;
}
int input(int *i,info* in[1000])//초기 입력 함수
{
(in[*i])=(info*)malloc(sizeof(info));
printf("Name:");
scanf("%s",in[*i]->name);
printf("Phone_number:");
scanf("%s",in[*i]->phone);
*i = *i + 1;
return 0;
}
int output(int *i,info* in[1000])//출력 함수
{
int l;
for(l=0;l<*i;l++){//입력된 순서대로 출력
printf("Name:%s--->Phone_number:%s--->address:%lld\n",in[l]->name,in[l]->phone,&in[l]);
}
return 0;
}
int search(int *i,info* in[1000])//검색함수
{
int l;
char search_name[20];
printf("Name:");
scanf("%s",search_name);
for(l=0;l<*i;l++)//입력한 값과 저장된값을 비교후 같은 값이 있으면 이름과 번호 출력
{
if(strcmp(search_name,in[l]->name) == 0){
printf("Name:%s--->Phone_number:%s--->address:%lld\n",in[l]->name,in[l]->phone,&in[l]);
break;
}
}
return 0;
}
int del(int *i,info* in[1000])//삭제함수
{
int l,k,p;
char del_name[20];
printf("Name:");
scanf("%s",del_name);
for(l=0;l<(*i);l++){//검색한 이름이 있는지 확인
if(strcmp(del_name,in[l]->name)==0){
for(k=l;k<(*i) && in[k+1] != NULL;k++){//이름이 있다면 다음 배열들을 한칸씩 앞으로 복사
strcpy(in[k]->name,in[k+1]->name);
strcpy(in[k]->phone,in[k+1]->phone);
p=k;
}
free(in[p+1]);//배열 복사후 마지막 메모리를 초기화
in[p+1]=NULL;
*i = (*i)-1;
return 0;
}
else
continue;
}
return 0;
}
int modify(int *i,info* in[1000])//수정 함수
{
int l;
char mody_name[20];
char new_phone[30];
printf("Name:");
scanf("%s",mody_name);
for(l=0;l<(*i);l++){//검색한 이름이 있는지 확인
if(strcmp(mody_name,in[l]->name)==0){//있다면 수정할 전화번호 입력받음
printf("New_Phone_number:");
scanf("%s",new_phone);
strcpy(in[l]->phone,new_phone);//입력받은 전화번호를 원래 배열에 복사
break;
}
}
return 0;
}
int free_all(int *i,info *in[1000])
{
int k;
for(k=0;k<(*i);k++){
free(in[k]);
in[k]=NULL;
}
return 0;
}
int main()
{
int i=0,k;
info* infomation[1000];
for(k=0;k<1000;k++){
infomation[k]=NULL;
}
while(1){
menu();
switch(get_menu_num()){
case 1:
input(&i,infomation);
break;
case 2:
output(&i,infomation);
break;
case 3:
search(&i,infomation);
break;
case 4:
del(&i,infomation);
break;
case 5:
modify(&i,infomation);
break;
case 6:
free_all(&i,infomation);
return 0;
}
}
}
이대로 돌렸을때 그냥 돌리기엔 실행이 모든 기능도 잘 돌아가고 이상이 없는데
과제채점 프로그램에 돌리면 segmentation fault가 나오더군요.
오늘 하루종일 이것도 해보고 저것도 해봤는데
포인터 배열의 초기화를 다른 구조체를 잡고 그것의 주소 값으로 설정한후 돌리면
#include
#include
#include
typedef struct infomation{
char name[20];
char phone[30];
}info;//이름과 전화번호를 저장할 구조체
int menu()//메뉴 출력 함수
{
printf("*****Menu*****\n");
printf("<1.Registration><2.ShowAll><3.Search>\n");
printf("<4.Deletion><5.Modification><6.Exit>\n");
printf("Enter_the_menu_number:");
return 0;
}
int get_menu_num()//메뉴번호 선택 함수
{
int n;
scanf("%d",&n);
return n;
}
int input(int *i,info* in[1000])//초기 입력 함수
{
(in[*i])=(info*)malloc(sizeof(info));
printf("Name:");
scanf("%s",in[*i]->name);
printf("Phone_number:");
scanf("%s",in[*i]->phone);
*i = *i + 1;
return 0;
}
int output(int *i,info* in[1000])//출력 함수
{
int l;
for(l=0;l<*i;l++){//입력된 순서대로 출력
printf("Name:%s--->Phone_number:%s--->address:%lld\n",in[l]->name,in[l]->phone,&in[l]);
}
return 0;
}
int search(int *i,info* in[1000])//검색함수
{
int l;
char search_name[20];
printf("Name:");
scanf("%s",search_name);
for(l=0;l<*i;l++)//입력한 값과 저장된값을 비교후 같은 값이 있으면 이름과 번호 출력
{
if(strcmp(search_name,in[l]->name) == 0){
printf("Name:%s--->Phone_number:%s--->address:%lld\n",in[l]->name,in[l]->phone,&in[l]);
break;
}
}
return 0;
}
int del(int *i,info* in[1000],)//삭제함수
{
int l,k,p=0;
char del_name[20];
printf("Name:");
scanf("%s",del_name);
for(l=0;l<(*i);l++){//검색한 이름이 있는지 확인
if(strcmp(del_name,in[l]->name)==0){
for(k=l;k<(*i)-1;k++){//이름이 있다면 다음 배열들을 한칸씩 앞으로 복사
strcpy(in[k]->name,in[k+1]->name);
strcpy(in[k]->phone,in[k+1]->phone);
p=k;
}
free(in[p+1]);//배열 복사후 마지막 메모리를 초기화
in[p+1]=&null;
*i = (*i)-1;
return 0;
}
else
continue;
}
return 0;
}
int modify(int *i,info* in[1000])//수정 함수
{
int l;
char mody_name[20];
char new_phone[30];
printf("Name:");
scanf("%s",mody_name);
for(l=0;l<(*i);l++){//검색한 이름이 있는지 확인
if(strcmp(mody_name,in[l]->name)==0){//있다면 수정할 전화번호 입력받음
printf("New_Phone_number:");
scanf("%s",new_phone);
strcpy(in[l]->phone,new_phone);//입력받은 전화번호를 원래 배열에 복사
break;
}
}
return 0;
}
int main()
{
int i=0,k;
info null;
info* information[1000];
for(k=0;k<1000;k++)
information[k]=&null;
while(1){
menu();
switch(get_menu_num()){
case 1:
input(&i,information);
break;
case 2:
output(&i,information);
break;
case 3:
search(&i,information);
break;
case 4:
del(&i,information);
break;
case 5:
modify(&i,information);
break;
case 6:
return 0;
}
}
}
#include
#include
#include
typedef struct infomation{
char name[20];
char phone[30];
}info;//이름과 전화번호를 저장할 구조체
int menu()//메뉴 출력 함수
{
printf("*****Menu*****\n");
printf("<1.Registration><2.ShowAll><3.Search>\n");
printf("<4.Deletion><5.Modification><6.Exit>\n");
printf("Enter_the_menu_number:");
return 0;
}
int get_menu_num()//메뉴번호 선택 함수
{
int n;
scanf("%d",&n);
return n;
}
int input(int *i,info* in[1000])//초기 입력 함수
{
(in[*i])=(info*)malloc(sizeof(info));
printf("Name:");
scanf("%s",in[*i]->name);
printf("Phone_number:");
scanf("%s",in[*i]->phone);
*i = *i + 1;
return 0;
}
int output(int *i,info* in[1000])//출력 함수
{
int l;
for(l=0;l<*i;l++){//입력된 순서대로 출력
printf("Name:%s--->Phone_number:%s--->address:%lld\n",in[l]->name,in[l]->phone,&in[l]);
}
return 0;
}
int search(int *i,info* in[1000])//검색함수
{
int l;
char search_name[20];
printf("Name:");
scanf("%s",search_name);
for(l=0;l<*i;l++)//입력한 값과 저장된값을 비교후 같은 값이 있으면 이름과 번호 출력
{
if(strcmp(search_name,in[l]->name) == 0){
printf("Name:%s--->Phone_number:%s--->address:%lld\n",in[l]->name,in[l]->phone,&in[l]);
break;
}
}
return 0;
}
int del(int *i,info* in[1000],info nul)//삭제함수
{
int l,k,p=0;
char del_name[20];
printf("Name:");
scanf("%s",del_name);
for(l=0;l<(*i);l++){//검색한 이름이 있는지 확인
if(strcmp(del_name,in[l]->name)==0){
for(k=l;k<(*i)-1;k++){//이름이 있다면 다음 배열들을 한칸씩 앞으로 복사
strcpy(in[k]->name,in[k+1]->name);
strcpy(in[k]->phone,in[k+1]->phone);
p=k;
}
free(in[p+1]);//배열 복사후 마지막 메모리를 초기화
in[p+1]=&nul;
*i = (*i)-1;
return 0;
}
else
continue;
}
return 0;
}
int modify(int *i,info* in[1000])//수정 함수
{
int l;
char mody_name[20];
char new_phone[30];
printf("Name:");
scanf("%s",mody_name);
for(l=0;l<(*i);l++){//검색한 이름이 있는지 확인
if(strcmp(mody_name,in[l]->name)==0){//있다면 수정할 전화번호 입력받음
printf("New_Phone_number:");
scanf("%s",new_phone);
strcpy(in[l]->phone,new_phone);//입력받은 전화번호를 원래 배열에 복사
break;
}
}
return 0;
}
int main()
{
int i=0,k;
info nul;
info* information[1000];
for(k=0;k<1000;k++)
information[k]=&nul;
while(1){
menu();
switch(get_menu_num()){
case 1:
input(&i,information);
break;
case 2:
output(&i,information);
break;
case 3:
search(&i,information);
break;
case 4:
del(&i,information,nul);
break;
case 5:
modify(&i,information);
break;
case 6:
return 0;
}
}
}
이렇게 했을땐
*** glibc detected *** ./Main: free(): invalid pointer: 0xbfa47fca ***
이런 오류가 뜨네요 ㅠㅠ
뭐를 어떻게 해야되는지 모르겠습니다 ㅠㅠ
조언좀 해주세요 ㅠㅠ
ㅠㅠ
이거 코드 올리는게 뭔가 이상하게 되버린 ㅠㅠㅠ
code를 눈으로 보기는 어렵고 ^^.
code를 눈으로 보기는 어렵고 ^^. valgrind를 이용해서 실행해보세요. 도움이 되실겁니다.
- NULL을 &nul로 바꾸는 건 개악이구요.
- NULL을 &nul로 바꾸는 건 개악이구요. NULL로 하시는게 좋아요.
- 세그먼테이션 폴트가 날 때는 그 라인을 유심히 보셔야 하구요. 질문을 올리실 때도 에러메시지 전체를 올려주시구요.
- 아마 free(in[p+1)에서 났을 거 같구요. in[p+1]이 NULL 이거나 &nul 이어서 났을거구요. NULL로 구현하셨을 때는 free(NULL)을 하려고 하니 문제였고, &nul로 구현하셨을 때는 nul은 malloc으로 할당되지 않았는데 그걸 free 시킬려고 하니 invalid pointer 에러가 나는거구요.
- 자기가 수행해본 몇 가지 예제에서 잘 돈다고 항상 잘 돈다고 할 수 없는거구요.
- 채점 프로그램에서 어떤 시나리오로 돌렸길래 (무엇을 삽입하고 무엇을 삭제하고 등등) 세그먼테이션 폴트가 나는지 알 수 있으면, 그걸 그대로 따라 해보셔야 하구요.
- 만약 채점 프로그램이 시나리오를 알려주지 않는다면, 세그먼테이션 폴트가 난 라인이 free일테니까 삭제할 때 문제가 있구나 하고 추적하셔야 하구요.
- 언뜻 보니 하나 넣고 하나 삭제할 때 문제가 발생할 것 같네요. 한 번 해보시고 고쳐보세요.
참고로 삭제를 한다고 뒤의 모든 문자열을 복사하는 구현은 안좋습니다.
간단하게는 10개를 삽입 후 5번째를 삭제를 했다면 10번째 것만 5번째 위치로 옮겨주면 되구요.
옮길 때도 문자열을 복사하기 보다는, free(in[4]); in[4] = in[9]; 와 같이 포인터만 이동해주면 충분하죠.
댓글 달기