我在理解动态分配的数组时遇到了问题。
我正在尝试将字符串的文本文件读取到2d数组,以便稍后对其进行排序。现在,正如我的代码所说,它每隔一段时间抛出一次seg故障。这意味着我做错了什么。我一直在四处奔波,试图更好地了解malloc实际上做了什么,但我想测试并检查我的阵列是否正在填充。
我的程序从文本文件中提取除了字符串之外什么都没有,我试图将这些数据放入二维数组中。
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]);
因为这只是一个要点,在这里我已经关闭并释放了内存,输出是使用puts显示的,但不是来自底部的printf。将数据读取到阵列的ELI5版本将是惊人的。
提前谢谢
答案 0 :(得分:1)
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 bytes\n", 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 bytes\n", maxlen + 1);
exit(EXIT_FAILURE);
}
s = p;//set the pointer to the newly allocated memory
}
s[i++] = c;
}
s[i] = '\0';
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 bytes\n", 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("%s\n", strings[i]);
}
/* Free each individual string, then the array of strings */
for (i = 0; i < nstrings; i++) {
free(strings[i]);
}
free(strings);
return 0;
}
答案 1 :(得分:0)
我没有仔细观察,所以我可能会提供一个不完整的解决方案。
话虽如此,错误可能在这里:
realloc(words, lines_allocated + lines_allocated);
realloc如果成功返回新指针,如果幸运的话,它可以分配相邻的空格(这不会导致段错误。)
words = realloc(words, lines_allocated + lines_allocated);
会解决它,尽管您可能需要检查错误。