해결된 질문
작성
·
209
0
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
#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);
}
여기 있습니다!
항상 감사합니다!!