读取几百行后程序中断
Program breaks after a couple hundred lines have been read
我制作了一个扫描功能,基本上只是将文件的行扫描成一个名为 buffer
的 char *
。然而,在读取了几百行之后,程序就停止工作了。我刚收到一个程序已停止工作的弹出窗口 window。假设我在内存分配方面做错了什么,但我不确定是什么。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *scan_file(FILE *fp);
#define MAX_LINE 200
int main(void) {
FILE *fp = fopen("test.txt", "r");
char *contents = scan_file(fp);
printf("%s\n", contents);
return 0;
}
// Scan in file into a buffer. Returns a malloc-ed string
char *scan_file(FILE *fp) {
int buf_len = 1;
int contents_len = buf_len;
char *buffer = malloc(sizeof(char) * (MAX_LINE + 1));
char *contents = malloc(sizeof(char) * (buf_len + 1));
strcpy(contents, "[=10=]");
while (fgets(buffer, MAX_LINE, fp) != NULL) {
buf_len = strlen(buffer);
contents_len += buf_len;
realloc(contents ,contents_len);
strcat(contents, buffer);
strcpy(buffer, "[=10=]");
}
free(buffer);
return contents;
}
代码无法使用 return 值形式 realloc()
分配大小减少 1。
重复 strcat()
得到一个缓慢的 (n*n) 解决方案。
考虑对数组大小使用 size_t
而不是 int
。
与其调用变量 ...len
,不如考虑 ...size
来确认 字符串 中最后一个 空字符 的存在.
char *scan_file(FILE *fp) {
// int buf_len = 1;
size_t buf_size = 1;
// int contents_len = buf_len;
size_t contents_size = buf_size;
// char *buffer = malloc(sizeof(char) * (MAX_LINE + 1));
// fgets(..., MAX_LINE, ...) will only read up to MAX_LINE - 1 characters.
char *buffer = malloc(MAX_LINE);
char *contents = malloc(buf_size + 1u);
if (buffer == NULL || contents == NULL) {
fprintf(stderr, "Out of memory\n");
return EXIT_FAILURE;
}
// strcpy(contents, "[=10=]");
contents[0] = '[=10=]';
while (fgets(buffer, MAX_LINE, fp) != NULL) {
// buf_len = strlen(buffer);
buf_size = strlen(buffer) + 1u;
// contents_len += buf_len;
// realloc(contents ,contents_len);
void *p = realloc(contents ,contents_size + buf_size);
if (p == NULL) {
fprintf(stderr, "Out of memory\n");
return EXIT_FAILURE;
}
contents = p;
// strcat(contents, buffer);
strcpy(contents + contents_size, buffer);
// now add
contents_size += buf_size;
// Code here not truly needed, yet helps in debugging.
// strcpy(buffer, "[=10=]");
buffer[0] = '[=10=]';
}
free(buffer);
return contents;
}
- 使用
realloc()
s return 值
realloc(NULL, size)
就像 malloc(size)
一样工作;无需预分配
- 避免过度复制并且
strlen()
- 只需在您第一次(也是唯一一次)触摸数据时将其放在您想要的位置即可。
#include <stdio.h>
#include <stdlib.h>
char *scanfile (FILE *fp)
{
size_t size, used;
char *buff = NULL;
int ch;
for (size=used=0;; ) {
ch = getc(fp);
if (ch == EOF) break;
if (used+1 >= size) {
size_t newsize = used? 2*used: 1024 ;
char *tmp = realloc(buff, newsize);
if (!tmp) FAIL();
else {buff = tmp; size = newsize; }
}
buff[used++] = ch;
}
/* Nothing read: return NULL */
if (!used) return NULL;
buff[used++] = 0;
/* maybe realloc (shrink) buff here */
return buff;
}
我制作了一个扫描功能,基本上只是将文件的行扫描成一个名为 buffer
的 char *
。然而,在读取了几百行之后,程序就停止工作了。我刚收到一个程序已停止工作的弹出窗口 window。假设我在内存分配方面做错了什么,但我不确定是什么。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *scan_file(FILE *fp);
#define MAX_LINE 200
int main(void) {
FILE *fp = fopen("test.txt", "r");
char *contents = scan_file(fp);
printf("%s\n", contents);
return 0;
}
// Scan in file into a buffer. Returns a malloc-ed string
char *scan_file(FILE *fp) {
int buf_len = 1;
int contents_len = buf_len;
char *buffer = malloc(sizeof(char) * (MAX_LINE + 1));
char *contents = malloc(sizeof(char) * (buf_len + 1));
strcpy(contents, "[=10=]");
while (fgets(buffer, MAX_LINE, fp) != NULL) {
buf_len = strlen(buffer);
contents_len += buf_len;
realloc(contents ,contents_len);
strcat(contents, buffer);
strcpy(buffer, "[=10=]");
}
free(buffer);
return contents;
}
代码无法使用 return 值形式 realloc()
分配大小减少 1。
重复 strcat()
得到一个缓慢的 (n*n) 解决方案。
考虑对数组大小使用 size_t
而不是 int
。
与其调用变量 ...len
,不如考虑 ...size
来确认 字符串 中最后一个 空字符 的存在.
char *scan_file(FILE *fp) {
// int buf_len = 1;
size_t buf_size = 1;
// int contents_len = buf_len;
size_t contents_size = buf_size;
// char *buffer = malloc(sizeof(char) * (MAX_LINE + 1));
// fgets(..., MAX_LINE, ...) will only read up to MAX_LINE - 1 characters.
char *buffer = malloc(MAX_LINE);
char *contents = malloc(buf_size + 1u);
if (buffer == NULL || contents == NULL) {
fprintf(stderr, "Out of memory\n");
return EXIT_FAILURE;
}
// strcpy(contents, "[=10=]");
contents[0] = '[=10=]';
while (fgets(buffer, MAX_LINE, fp) != NULL) {
// buf_len = strlen(buffer);
buf_size = strlen(buffer) + 1u;
// contents_len += buf_len;
// realloc(contents ,contents_len);
void *p = realloc(contents ,contents_size + buf_size);
if (p == NULL) {
fprintf(stderr, "Out of memory\n");
return EXIT_FAILURE;
}
contents = p;
// strcat(contents, buffer);
strcpy(contents + contents_size, buffer);
// now add
contents_size += buf_size;
// Code here not truly needed, yet helps in debugging.
// strcpy(buffer, "[=10=]");
buffer[0] = '[=10=]';
}
free(buffer);
return contents;
}
- 使用
realloc()
s return 值 realloc(NULL, size)
就像malloc(size)
一样工作;无需预分配- 避免过度复制并且
strlen()
- 只需在您第一次(也是唯一一次)触摸数据时将其放在您想要的位置即可。
#include <stdio.h>
#include <stdlib.h>
char *scanfile (FILE *fp)
{
size_t size, used;
char *buff = NULL;
int ch;
for (size=used=0;; ) {
ch = getc(fp);
if (ch == EOF) break;
if (used+1 >= size) {
size_t newsize = used? 2*used: 1024 ;
char *tmp = realloc(buff, newsize);
if (!tmp) FAIL();
else {buff = tmp; size = newsize; }
}
buff[used++] = ch;
}
/* Nothing read: return NULL */
if (!used) return NULL;
buff[used++] = 0;
/* maybe realloc (shrink) buff here */
return buff;
}