标题解释了问题。在我的程序中的这个函数中,每当我在数组中分配一定大小时,我的终端上就会收到大量的错误代码。数组被正确复制,但是在打印完成后,程序崩溃了。该程序的目的是从文件中读取,然后将每一行存储在数组索引中。非常感谢您的帮助。谢谢
数组在main中声明为指针,然后在内部动态分配。
void read_file_into_array(char **filearray, FILE * fp)
{
/* use get line to count # of lines */
int numlines = -1;
numlines = linecount(fp);
size_t size = 50;
char *buffer;
buffer = (char *)malloc(size * sizeof(char));
if (buffer == NULL) {
perror("Unable to allocate buffer");
exit(1);
}
if (numlines < 0) {
fprintf(stderr, "error: unable to determine file length.\n");
return;
}
printf(" number of lines counted are ; %d\n", numlines);
/* allocate array of size numlines + 1 */
if (!(*filearray = (char *)malloc(numlines + 1 * sizeof(char)))) {
fprintf(stderr, "error: virtual memory exhausted.\n");
return;
}
fseek(fp, 0, SEEK_SET);
for (int i = 0; i < numlines; i++) {
if (!feof(fp)) {
fgets(buffer, size, fp);
filearray[i] = (char *)malloc(size * sizeof(char *));
strcpy(filearray[i], buffer);
printf("buffer at %d : %s\n", i, buffer);
printf("array at %d : %s\n", i, filearray[i]);
}
}
free(buffer);
}
/* THIS IS MY MAIN BELOW */
int main (int argc, char **argv)
{
FILE *fp = NULL;
char* array;
/* open file for reading (default stdin) */
fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open */
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
return 1;
}
read_file_into_array (&array, fp);
if (fp != stdout)
if (fclose (fp) == EOF) {
fprintf (stderr, "error: fclose() returned EOF\n");
return 1;
}
return 0;
}
/* MY LNE COUNT FUNCITON */
int linecount(FILE *fp) {
char buff[MAXLINE];
int count = 0;
while(fgets(buff,MAXLINE,fp) != NULL) {
count++;
}
return count;
}
答案 0 :(得分:0)
您收到编译警告的主要问题之一(+注意指出代码中其他不同错误的注释)是
if (!(*filearray = (char**)malloc(sizeof(char*) * (numlines + 1))))
*filearray
的类型为char*
而不是char**;
+,无需转换malloc
返回的值。
char **filearray
实际上来自&array
的{{1}},其定义为main()
现在,以下内容完全打破了稳定性并导致未定义的行为
char *array;
这相当于主要的filearray[i] = (char *)malloc(size * sizeof(char *));
,这是完全打破。您正在遍历堆栈,从(&array)[i] = (char *)malloc(size * sizeof(char *));
的{{1}}位置开始,只需覆盖array
返回的main
值的所有内容。
如果您希望char*
为字符串数组,将其定义为malloc
,请通过指针array
传递,相应地更新声明和char **array
的用法。
答案 1 :(得分:0)
好的,让我们整理出来。首先,要将pointer to pointer to char
作为参数传递给函数,在函数内分配并在调用函数中返回结果(不再有),必须传递 的地址指向char的指针。否则,函数会收到一个副本,并且函数中所做的任何更改都不会在调用者(main
此处)中返回,因为复制丢失(分配块的起始地址丢失)回报。
将指针的地址传递给指向char的指针意味着您必须成为 3-STAR程序员(这不是恭维)。一个更好的方法是根本不传递指针,只需在函数内分配,然后返回一个指向调用者的指针(但在某些情况下,你仍然需要将它作为参数传递,所以如下所示)
下面的程序将读取作为第一个参数传递的任何文本文件(如果没有给出参数,它将从stdin
读取)。它将动态分配指针并且需要(在MAXL
块中而不是一次一个,这是非常低效的)。它将根据需要分配(和重新分配)行以容纳任何长度的行。它使用MAXC
个字符的固定缓冲区来连续读取,直到读取完整的行,将offset
保存到当前行中的位置,以根据需要附加后续读取。
最后,在读取文件后,它会将文本和关联的行号打印到stdout
,并在退出之前释放所有已分配的内存。仔细看看,如果您有任何问题,请告诉我:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXL = 32, MAXC = 1024 };
char **read_file_into_buf (char ***buf, FILE *fp, int *nlines);
int main (int argc, char **argv) {
char **buf = NULL; /* buffer to hold lines of file */
int n; /* number of lines read */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
if (read_file_into_buf (&buf, fp, &n)) { /* read file into buf */
for (int i = 0; i < n; i++) { /* loop over all lines */
printf ("line[%3d]: %s\n", i, buf[i]); /* output line */
free (buf[i]); /* free line */
}
free (buf); /* free buffer */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
/** read text file from 'fp' into 'buf' update 'nlines'.
* Being a 3-STAR Programmer, is NOT a compliment. However,
* to pass a pointer to pointer to char as a parameter and
* allocate within the function, it is required. You must
* pass the address of buf from main otherwise the function
* recieves a copy whose allocation is lost on return. A better
* approach is to simply assign the return in 'main' and not
* pass buf at all.
*/
char **read_file_into_buf (char ***buf, FILE *fp, int *nlines)
{
/* current allocation, current index, and offset (if less
* than a whole line is read into line on fgets call), and
* eol indicates '\n' present.
*/
size_t n = MAXL, idx = 0, offset = 0, eol = 0;
char line[MAXC] = ""; /* temp buffer for MAXC chars */
void *tmp = NULL; /* pointer for realloc */
/* validate address, file ptr & nlines address */
if (!buf || !fp || !nlines) {
fprintf (stderr, "error; invalid parameter.\n");
return NULL;
}
/* allocate initial MAXL pointers, calloc used to avoid valgrind
* warning about basing a conditional jump on uninitialized value.
* calloc allocates and initializes.
*/
if (!(*buf = calloc (sizeof *buf, MAXL))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return NULL;
}
while (fgets (line, MAXC, fp)) /* read every line in file */
{
/* save offset from prior read (if any), get len */
size_t end = offset, len = strlen (line);
if (line[len - 1] == '\n') { /* test for new line */
line[--len] = 0; /* overwrite with nul */
offset = 0; /* zero offset, all read */
eol = 1; /* POSIX eol present */
}
else {
line[len] = 0; /* nul-terminate */
offset += len; /* short read, save offset to last char */
eol = 0; /* no POSIX eol */
}
/* allocate/reallocate for current line + nul-byte */
tmp = realloc ((*buf)[idx], sizeof ***buf * (end + len + 1));
if (!tmp) {
fprintf (stderr, "error: realloc, memory exhausted.\n");
return *buf; /* return current buf */
}
(*buf)[idx] = tmp; /* assign block to current index */
strcpy ((*buf)[idx] + end, line); /* copy line to block */
if (!eol) continue; /* chars remain in line, go read them */
if (++idx == n) { /* check pointer allocation, realloc as needed */
tmp = realloc (*buf, sizeof **buf * (n + MAXL));
if (!tmp) {
fprintf (stderr, "error: realloc buf, memory exhausted.\n");
return *buf;
}
*buf = tmp; /* assign new block to *buf */
memset (*buf + n, 0, sizeof **buf * MAXL); /* zero new memory */
n += MAXL; /* update the current number of ptrs allocated */
}
*nlines = idx; /* update the number of lines read */
}
if (!eol) { /* protect against file with no POSIX ending '\n' */
idx++; /* account for final line */
*nlines = idx; /* update nlines */
}
/* final realloc to size buf to exactly fit number of lines */
tmp = realloc (*buf, sizeof **buf * (idx));
if (!tmp) /* if it fails, return current buf */
return *buf;
*buf = tmp; /* assign reallocated block to buf */
return *buf;
}
注意:将使用memset (*buf + n, 0, sizeof **buf * MAXL);
分配的新指针归零是可选的,但它会消除valgrind
有关基于未初始化值的条件跳转的警告,就像使用{{ 1}}的初始指针。 calloc/malloc
无法选择归零,因此需要单独调用realloc
。
示例使用/输出
memset
在你编写的动态分配内存的任何代码中,你有2个职责关于任何分配的内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放。
您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已拥有释放了你分配的所有内存。
对于Linux $ ./bin/fgets_readfile < dat/damages.txt
line[ 0]: Personal injury damage awards are unliquidated
line[ 1]: and are not capable of certain measurement; thus, the
line[ 2]: jury has broad discretion in assessing the amount of
line[ 3]: damages in a personal injury case. Yet, at the same
line[ 4]: time, a factual sufficiency review insures that the
line[ 5]: evidence supports the jury's award; and, although
line[ 6]: difficult, the law requires appellate courts to conduct
line[ 7]: factual sufficiency reviews on damage awards in
line[ 8]: personal injury cases. Thus, while a jury has latitude in
line[ 9]: assessing intangible damages in personal injury cases,
line[ 10]: a jury's damage award does not escape the scrutiny of
line[ 11]: appellate review.
line[ 12]:
line[ 13]: Because Texas law applies no physical manifestation
line[ 14]: rule to restrict wrongful death recoveries, a
line[ 15]: trial court in a death case is prudent when it chooses
line[ 16]: to submit the issues of mental anguish and loss of
line[ 17]: society and companionship. While there is a
line[ 18]: presumption of mental anguish for the wrongful death
line[ 19]: beneficiary, the Texas Supreme Court has not indicated
line[ 20]: that reviewing courts should presume that the mental
line[ 21]: anguish is sufficient to support a large award. Testimony
line[ 22]: that proves the beneficiary suffered severe mental
line[ 23]: anguish or severe grief should be a significant and
line[ 24]: sometimes determining factor in a factual sufficiency
line[ 25]: analysis of large non-pecuniary damage awards.
是正常的选择。
valgrind
始终确认释放所有堆块 - 不可能泄漏并且同样重要错误摘要:0个上下文中的0个错误。 (虽然注意:某些操作系统没有提供足够的记忆排除文件(排除系统和操作系统内存不被报告为正在使用的文件),这将导致$ valgrind ./bin/fgets_readfile < dat/damages.txt
==5863== Memcheck, a memory error detector
==5863== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5863== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5863== Command: ./bin/fgets_readfile
==5863==
line[ 0]: Personal injury damage awards are unliquidated
line[ 1]: and are not capable of certain measurement; thus, the
line[ 2]: jury has broad discretion in assessing the amount of
line[ 3]: damages in a personal injury case. Yet, at the same
line[ 4]: time, a factual sufficiency review insures that the
line[ 5]: evidence supports the jury's award; and, although
line[ 6]: difficult, the law requires appellate courts to conduct
line[ 7]: factual sufficiency reviews on damage awards in
line[ 8]: personal injury cases. Thus, while a jury has latitude in
line[ 9]: assessing intangible damages in personal injury cases,
line[ 10]: a jury's damage award does not escape the scrutiny of
line[ 11]: appellate review.
line[ 12]:
line[ 13]: Because Texas law applies no physical manifestation
line[ 14]: rule to restrict wrongful death recoveries, a
line[ 15]: trial court in a death case is prudent when it chooses
line[ 16]: to submit the issues of mental anguish and loss of
line[ 17]: society and companionship. While there is a
line[ 18]: presumption of mental anguish for the wrongful death
line[ 19]: beneficiary, the Texas Supreme Court has not indicated
line[ 20]: that reviewing courts should presume that the mental
line[ 21]: anguish is sufficient to support a large award. Testimony
line[ 22]: that proves the beneficiary suffered severe mental
line[ 23]: anguish or severe grief should be a significant and
line[ 24]: sometimes determining factor in a factual sufficiency
line[ 25]: analysis of large non-pecuniary damage awards.
==5863==
==5863== HEAP SUMMARY:
==5863== in use at exit: 0 bytes in 0 blocks
==5863== total heap usage: 28 allocs, 28 frees, 1,733 bytes allocated
==5863==
==5863== All heap blocks were freed -- no leaks are possible
==5863==
==5863== For counts of detected and suppressed errors, rerun with: -v
==5863== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
报告有些记忆尚未被释放(尽管你已经完成了自己的工作并释放了你分配并在你控制下的阻止。)