我在理解动态分配的数组方面确实有问题。
我试图读取字符串的文本文件到2d数组,这样我就可以把它们整理出来。现在我的代码每隔一段时间就会抛出seg错误。也就是说我做错了什么。我一直在冲浪,试图更好地理解malloc实际上做了什么,但我想测试和检查我的数组是否被填充。
我的程序是从一个文本文件,但没有字符串,我试图把这些数据到一个2d数组。
for(index = 0; index < lines_allocated; index++){
//for loop to fill array 128 lines at a time(arbitrary number)
words[index] = malloc(sizeof(char));
if(words[index] == NULL){
perror("too many characters");
exit(2);
}
//check for end of file
while(!feof(txt_file)) {
words = fgets(words, 64, txt_file);
puts(words);
//realloc if nessesary
if (lines_allocated == (index - 1)){
realloc(words, lines_allocated + lines_allocated);
}
}
}
//get 3rd value placed
printf("%s", words[3]);
因为这只是一个要点,在这里我关闭并释放了内存,输出是使用put显示的,而不是从底部打印的。将文件读取到数组的ELI5版本将是令人惊叹的。
提前感谢
void *malloc(size_t n)将分配一个n字节的区域,并返回指向该区域第一个字节的指针,如果无法分配足够的空间,则返回NULL。所以当你执行malloc(sizeof(char))时,你只为一个字节分配了足够的空间(sizeof(char)总是定义为1)。
下面是一个带注释的示例,展示了malloc、realloc和free的正确用法。它从文件中读取0到8行,每一行都包含一个未知长度的字符串。然后打印每一行并释放所有内存。#include <stdio.h>
#include <stdlib.h>
/* An issue with reading strings from a file is that we don't know how long
they're going to be. fgets lets us set a maximum length and discard the
rest if we choose, but since malloc is what you're interested in, I'm
going to do the more complicated version in which we grow the string as
needed to store the whole thing. */
char *read_line(void) {
size_t maxlen = 16, i = 0;
int c;
/* sizeof(char) is defined to be 1, so we don't need to include it.
the + 1 is for the null terminator */
char *s = malloc(maxlen + 1);
if (!s) {
fprintf(stderr, "ERROR: Failed to allocate %zu bytesn", maxlen + 1);
exit(EXIT_FAILURE);
}
/* feof only returns 1 after a read has *failed*. It's generally
easier to just use the return value of the read function directly.
Here we'll keep reading until we hit end of file or a newline. */
while ('n' != (c = getchar())) {
if (EOF == c) {
/* We return NULL to indicate that we hit the end of file
before reading any characters, but if we've read anything,
we still want to return the string */
if (0 == i) return NULL;
break;
}
if (i == maxlen) {
/* Allocations are expensive, so we don't want to do one each
iteration. As such, we're always going to allocate more than
we need. Exactly how much extra we allocate depends on the
program's needs. Here, we just add a constant amount. */
maxlen += 16;
/* realloc will attempt to resize the memory pointed to by s,
or copy it to a newly allocated region of size maxlen. If it
makes a copy, it will free the old version. */
char *p = realloc(s, maxlen + 1);
if (!p) {
/* If the realloc fails, it does not free the old version, so we do it here. */
free(s);
fprintf(stderr, "ERROR: Failed to allocate %zu bytesn", maxlen + 1);
exit(EXIT_FAILURE);
}
s = p;//set the pointer to the newly allocated memory
}
s[i++] = c;
}
s[i] = ' ';
return s;
}
int main(void) {
/* If we wanted to, we could grow the array of strings just like we do the strings
themselves, but for brevity's sake, we're just going to stop reading once we've
read 8 of them. */
size_t i, nstrings = 0, max_strings = 8;
/* Each string is an array of characters, so we allocate an array of char*;
each char* will point to the first element of a null-terminated character array */
char **strings = malloc(sizeof(char*) * max_strings);
if (!strings) {
fprintf(stderr, "ERROR: Failed to allocate %zu bytesn", sizeof(char*) * max_strings);
return 1;
}
for (nstrings = 0; nstrings < max_strings; nstrings++) {
strings[nstrings] = read_line();
if (!strings[nstrings]) {//no more strings in file
break;
}
}
for (i = 0; i < nstrings; i++) {
printf("%sn", strings[i]);
}
/* Free each individual string, then the array of strings */
for (i = 0; i < nstrings; i++) {
free(strings[i]);
}
free(strings);
return 0;
}
我没有仔细观察,所以我可能会提供一个不完整的解决方案。
也就是说,错误可能在这里:
realloc(words, lines_allocated + lines_allocated);
realloc如果成功返回新的指针,如果幸运的话,它可以分配相邻的空间(这不会导致段错误)。
words = realloc(words, lines_allocated + lines_allocated);
可以解决这个问题,尽管您可能需要检查错误。