struct book* read_books 예제에서 쓰인 malloc()에 대해 질문합니다.
struct book* read_books(const char* filename, int* n)
{
FILE* fp;
int count;
char buffer[SLEN] = { '\0', };
struct book* books;
if ((fp = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Can't open \"%s\" file.\n", filename);
exit(EXIT_FAILURE);
}
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
count = atoi(buffer);
*n = count;
books = (struct book*)malloc(sizeof(struct book) * count);
if (!books)
{
printf("Malloc failed");
exit(1);
}
for (int i = 0; i < count; ++i)
{
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
strcpy(books[i].name, buffer);
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
strcpy(books[i].author, buffer);
}
fclose(fp);
return books;
}
제가 작성한 read_books 코드입니다. fscanf()도 %[^\n]%*c 가 사용되는지 몰라서 string.h을 이용해서 저렇게 작성을 하였는데
빌드도 잘 되고 작동도 잘 되는데 strcpy(books[i].name, buffer); 에서 warning이 뜹니다. 정확히
C6385 Reading invalid data from 'books': the readable size is 'sizeof(book)*count' bytes, but '404' bytes may be read.
이렇게 뜨는데 코드를 바꿔가면서 알아보니깐 books = (struct book*)malloc(sizeof(struct book) * count); 이 부분에서
count를 상수로 바꾸면 오류가 안 뜹니다. 또 교수님이 calloc()을 쓰시길래 calloc()으로 바꿨더니 상수로 바꿨을 때처럼 오류가 사라졌습니다. 그 이유가 궁금합니다.
또 교수님께서 calloc()에서 size_t _count부분에 size를 size_t _size부분에 count를 넣으셨는데 이 부분을 바꿔도
동적할당된 힙 메모리를 가리키는 포인터를 배열처럼 사용하는데 전혀 문제가 발생하지 않는지, 또 그 이유는 무엇인지 궁금합니다.
답변 2
1
1. count 는 런타임에 값이 결정되며 런타임 중에 값이 계속해서 변할 수 있는 일반 변수이기에 워닝을 띄워주는 듯 합니다. 워닝을 띄우는 시점은 컴파일 타임인데 사실 컴파일 타임엔 진짜 sizeof(book)*count 가 404byte 를 넘어 오버플로우가 될지는 알 수가 없구요, 컴파일 타임에 체크해줄 수 없으니 그냥 조심하라는 경고 정도로 생각해주시면 될 것 같습니다! count 가 상수라면 컴파일 타임에도 404byte 를 넘지 않을지 확실하게 알 수가 있으니까 워닝이 없는 것으로 생각이 되구요, calloc 은 두 개의 인자를 받음으로써 오버플로우 될 수 있을지를 미리 체크할 수 있다고 합니다. https://stackoverflow.com/questions/4083916/two-arguments-to-calloc
2. 이 부분은 코드에서도 강의에서도 제가 못 찾겠네요 ㅠ (질문 주실 때 강의 시간대 함께 꼭 남겨주실 것을 부탁드립니다!) 근데 아마 질문해주신 것만 봐서는 포인터를 배열처럼 사용하는 것과는 전혀 상관없어 보입니다. 그냥 포인터는 원래 배열처럼 [] 연산자를 사용할 수 있습니다. [] 도 곧 포인터 산술연산이니까요!
1
안녕하세요!
저는 해당 워닝이 발생하지 않는데 혹시 전체 코드 주실 수 있을까요?
0
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define SLEN 101
struct book
{
char name[SLEN];
char author[SLEN];
};
void print_books(const struct book* books, int n);
void write_books(const char* filename, const struct book* books, int n);
struct book* read_books(const char* filename, int* n);
void read_books2(const char* filename, struct book** books_dptr, int* n);
int main()
{
int temp;
int n = 3;
struct book* my_books = (struct book*)malloc(sizeof(struct book) * 3);
if (!my_books) {
printf("Malloc failed");
exit(1);
}
my_books[0] = (struct book){ "The Great Gatsby", "F. Scott Fitzgerald" };
my_books[1] = (struct book){ "Hamlet", "William Shakespeare" };
my_books[2] = (struct book){ "The Odyssey", "Homer" };
print_books(my_books, n);
printf("\nWriting to a file.\n");
write_books("books.txt", my_books, n);
free(my_books);
n = 0;
printf("Done.\n");
printf("\nPress any key to read data from a file.\n\n");
temp = _getch();
my_books = read_books("books.txt", &n);
//read_books2("books.txt", &my_books, &n);
print_books(my_books, n);
free(my_books);
n = 0;
return 0;
}
void print_books(const struct book* books, int n)
{
for (int i = 0; i < n; ++i)
{
printf("Book %d : \"%s\" written by \"%s\"\n",
i + 1, books[i].name, books[i].author);
}
}
void write_books(const char* filename, const struct book* books, int n)
{
FILE* fp;
if ((fp = fopen(filename, "w")) == NULL)
{
fprintf(stderr, "Can't open \"%s\" file.\n", filename);
exit(EXIT_FAILURE);
}
fprintf(fp, "%d\n", n);
for (int i = 0; i < n; ++i)
{
fputs(books[i].name, fp);
fprintf(fp, "\n");
fputs(books[i].author, fp);
fprintf(fp, "\n");
}
fclose(fp);
}
struct book* read_books(const char* filename, int* n)
{
FILE* fp;
int count;
char buffer[SLEN] = { '\0', };
struct book* books;
if ((fp = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Can't open \"%s\" file.\n", filename);
exit(EXIT_FAILURE);
}
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
count = atoi(buffer);
*n = count;
books = (struct book*)malloc(sizeof(struct book) * count);
if (!books)
{
printf("Malloc failed");
exit(1);
}
for (int i = 0; i < count; ++i)
{
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
strcpy(books[i].name, buffer);
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
strcpy(books[i].author, buffer);
}
fclose(fp);
return books;
}
void read_books2(const char* filename, struct book** books_dptr, int* n)
{
FILE* fp;
int count;
char buffer[SLEN] = { '\0', };
if ((fp = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Can't open \"%s\" file.\n", filename);
exit(EXIT_FAILURE);
}
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
count = atoi(buffer);
*n = count;
for (int i = 0; i < count; ++i)
{
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == '\n')
buffer[i] = '\0';
}
strcpy((*books_dptr)[i].name, buffer);
fgets(buffer, SLEN, fp);
for (int i = 0; i < SLEN; ++i)
{
if (buffer[i] == "\n")
buffer[i] = '\0';
}
strcpy((*books_dptr)[i].author, buffer);
}
fclose(fp);
}
여기 있습니다!
Export template 안됨
1
63
2
완전히 똑같이 따라해도 exe파일이 안만들어져서 실행이 안됩니다.
1
88
3
main 함수에서 왜 int만 선언이 되는걸까요
1
78
2
8비트 2진수 변환시 왜 1을 더해야하나요?
1
75
2
혹시 강의를 빠르게 수강하려면 어디서부터 듣는게 좋을까요?
1
78
1
프로토타입과 함수간의 인자 불일치
1
87
2
12.12 헤더 관련 질문
1
74
2
Visual Studio Community 2026 사용 문의
1
170
2
Q. 15:30, 부호가 있는 8비트 정수 질문
1
72
2
getchar(), putchar()
1
111
3
강의자리ㅛ
1
93
2
비주얼스튜디오코드로 공부해도 상관없나요?
1
127
2
소스파일안에 여러 파일
1
87
2
F5와 F7의 차이
1
90
2
c = TWO * (a+b); 에서 a와 b는?
1
67
2
; 세미콜론을 붙이는 기준에 문의
1
78
1
Step over 기능 문의
1
64
2
2.6 강의 따옴표 출력 규칙 문의
1
87
2
int main 함수 관련 오류 문의
1
76
2
13.4 words[0]
0
73
2
11.7 함수를 구현해 봤습니다.
1
67
2
11.6 직접 strcmp와 strncmp를 구현해 보았습니다.
1
71
2
11.6 my_strcat과 my_strncat을 구현해봤습니다.
1
60
2
11.6 fit_str함수를 구현해 봤습니다.
1
59
2





