分配数组C时检测到堆栈崩溃

分配数组C时检测到堆栈崩溃,c,stack-overflow,C,Stack Overflow,正如标题所解释的那样。在我的程序中的这个函数中,每当我在数组中分配一定的大小时,终端上就会出现大量的错误代码。数组被正确复制,但在打印后程序崩溃。该程序的目的是从文件中读取数据,然后将每一行存储在数组索引中。非常感谢你的帮助。谢谢 数组在main中声明为指针,然后在内部动态分配 void read_file_into_array(char **filearray, FILE * fp) { /* use get line to count # of

正如标题所解释的那样。在我的程序中的这个函数中,每当我在数组中分配一定的大小时,终端上就会出现大量的错误代码。数组被正确复制,但在打印后程序崩溃。该程序的目的是从文件中读取数据,然后将每一行存储在数组索引中。非常感谢你的帮助。谢谢

数组在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;
}
void将文件读入数组(char**filearray,file*fp)
{
/*使用get line计算行数*/
int numlines=-1;
numlines=行数(fp);
尺寸=50;
字符*缓冲区;
缓冲区=(char*)malloc(size*sizeof(char));
if(buffer==NULL){
perror(“无法分配缓冲区”);
出口(1);
}
if(numlines<0){
fprintf(stderr,“错误:无法确定文件长度。\n”);
返回;
}
printf(“计数的行数为;%d\n”,numlines);
/*分配大小为numlines+1的数组*/
如果(!(*filearray=(char*)malloc(numlines+1*sizeof(char))){
fprintf(stderr,“错误:虚拟内存耗尽。\n”);
返回;
}
fseek(fp,0,SEEK_集);
对于(int i=0;i1?fopen(argv[1],“r”):stdin;
如果(!fp){/*验证文件打开*/
fprintf(stderr,“错误:文件打开失败“%s”\n”,argv[1]);
返回1;
}
将\u文件\u读入\u数组(&array,fp);
如果(fp!=stdout)
如果(fclose(fp)=EOF){
fprintf(stderr,“错误:fclose()返回EOF\n”);
返回1;
}
返回0;
}
/*我的LNE计数函数*/
整数行数(文件*fp){
字符buff[MAXLINE];
整数计数=0;
while(fgets(buff,MAXLINE,fp)!=NULL){
计数++;
}
返回计数;
}

为什么会出现编译警告(注意指出代码中其他不同错误的注释)的一个主要问题是

  • if(!(*filearray=(char**)malloc(sizeof(char*)*(numlines+1))
  • *filearray
    的类型为
    char*
    而不是
    char**+无需强制转换
    malloc
    返回的值

  • char**filearray
    实际上是定义为
    char*数组的
    main()
    中的
    &array

  • 现在,以下内容完全破坏了稳定性,并导致未定义的行为

    filearray[i] = (char *)malloc(size * sizeof(char *));
    
    这相当于
    (&array)[i]=(char*)malloc(size*sizeof(char*))从主目录中,这是完全损坏的。您正在遍历堆栈,从
    main
    数组的位置开始,只需使用
    malloc
    返回的
    char*
    值覆盖所有内容


    如果您希望您的
    数组
    是字符串数组,请将其定义为
    字符**数组
    ,通过指针
    和数组
    传递它,相应地更新
    文件数组
    的声明和用法。

    好的,让我们来整理一下。首先,要将指向char的指针的
    指针作为参数传递给函数,请在函数内进行分配,并将结果返回调用函数中(无更多),必须传递指向char的指针的地址。否则,函数将接收一个副本,并且在调用方(
    main
    此处)中对函数所做的任何更改都不可用,因为当函数返回时副本丢失(分配块开始的地址丢失)

    将指针的地址传递给指向char的指针意味着您必须成为一名三星级程序员(这不是恭维)。更好的方法是根本不传递指针,只需在函数中分配并返回一个指向调用者的指针(但在某些情况下,仍然需要将其作为参数传递,如下所示)

    下面的程序将读取作为第一个参数传递的任何文本文件(或者,如果没有给出参数,它将从
    stdin
    读取)。它将动态分配指针和所需的指针(在
    MAXL
    块中,而不是一次分配一个指针,这是非常低效的)。它将根据需要分配(和重新分配)线路,以适应任何长度的线路。它使用
    MAXC
    chars的固定缓冲区连续读取,直到读取完一行,将
    偏移量保存到当前行中的位置,以便根据需要追加后续读取

    最后,在读取文件后,它会将文本和相关行号打印到
    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;
    }
    
    在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)它可以是fr
    $ ./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 ./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)