realloc не работает для указателей на указатели - PullRequest
0 голосов
/ 02 ноября 2019

Когда я пытаюсь использовать realloc для внешнего указателя указателей, адрес памяти продолжает меняться, хотя я возвращаю его к исходному указателю.

Вот код ниже. realloc находится в функции read_list. Я попытался воспроизвести проблему, просто используя указатель barebones для указателя и перераспределения, и это сработало, поэтому ошибка может быть в другом месте, но я не могу точно определить ее, поэтому весь код включен.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define INIT_MEM 32

int read_list(char **, char *);

int main(int argc, char *argv[])
{
    char **dict;

    if (argc != 2) {
        fprintf(stderr, "[ERROR]: Usage is \"%s <dict> <list>\"\n", argv[0]);
        return(1);
    }

    dict = malloc(INIT_MEM);
    if (read_list(dict, argv[1])) return(1);
    printf("&dict[0]: %d\n", &dict[0]);

    return(0);
}

int read_list(char **dest, char *file_name)
{
    FILE *stream; /* list of words file */
    char ch; /* current char read */
    int i, j, k, start, read_mode; /* start: file position beginning of each line; see initializations for rest */
    int total_memory; /* COUNTS MEMORY */
    int i_mem = INIT_MEM; /* initial memory */

    stream = fopen(file_name, "r");

    if (stream == NULL) {
        fprintf(stderr, "[ERROR]: Invalid input file!");
        return(1);
    }

    i = 0, j = 0, k = 0, total_memory = 0; /* i: size counter; j = word counter; k = ch counter */
    read_mode = 1; /* 1: true; 0: false */ 
    while ((ch = fgetc(stream)) != EOF) { /* read in each characters */
        if (ch == '\n') { /* after reaching end of line */
            if (read_mode) { /* if in read-mode */
                while (total_memory >= i_mem) { /* allocate more memory for dest if hit upper limit */
                    i_mem *= 2; /* double the memory size */
                    printf("IN_TM_BEFORE@%d= &dest[0]: %d\n", i_mem, &dest[0]);
                    dest = realloc(dest, i_mem); /* allocate increased memory into dest */  
                    printf("IN_TM_AFTER@%d= &dest[0]: %d\n", i_mem, &dest[0]);
                    /* printf("i_mem:%d\n", i_mem); =================== */
                    if (dest == NULL) {
                        fprintf(stderr, "[ERROR]: Memory reallocation failed!\n");
                        return(1);
                    }
                }
                dest[j] = malloc(i); /* allocate string with i, the size of word*/
                total_memory += i + 1; /* increase allocated memory mount by size + 1 to account for pointer*/
                read_mode = 0; /* turn to transfer mode */
                fseek(stream, start - 1, SEEK_SET); /* move back to start of word to transfer */
            } else {
                i = 0, k = 0; /* reset */
                read_mode = 1; /* go to read mode */
                j++; /* allow recording for next word */
            }
        }
        else {
            if (read_mode) { /* determine length of string */
                if (i == 0) start = ftell(stream); /* record start of word for transfer mode */
                i++; /* count characters in word */
            } else { /* record string */
                dest[j][k++] = ch;
            }
        }
    }

    printf("FINAL: &dest[0]: %d\n", &dest[0]);

    return(0);
}

=============================== dict.txt ===============================

flyer
go
crabulus
prose
humperdoodle
moo
dragon
enderman
yellow
abonobo

Я уже пытался изменить внешний указатель (указатель, указывающий на указатели) на размер 5000 и удалить reallocи адреса памяти в порядке, но когда я включаю realloc, возникает проблема.

Когда я realloc, я получаю такой результат:

IN_TM_BEFORE@64= &dest[0]: 35962896
IN_TM_AFTER@64= &dest[0]: 35963690
IN_TM_BEFORE@128= &dest[0]: 35963690
IN_TM_AFTER@128= &dest[0]: 35963888
FINAL: &dest[0]: 35963888
&dict[0]: 35962896

Что, по-видимому, означает, чтопосле I realloc указатель не возвращается в dest, хотя я сделал dest = realloc(dest, i_mem);

1 Ответ

2 голосов
/ 02 ноября 2019

Дело в том, что вы устанавливаете локальную переменную, если вы хотите отразить изменение переменной, переданной в качестве аргумента, вам необходим дополнительный уровень косвенности, например:

int read_list(char ***dest, char *file_name)
{
  ...
  *dest = realloc(...);
}

int main(int argc, char *argv[])
{
  ..
  read_list(&dict, ...);
}

Это сделаетизменение видимо снаружи, в противном случае изменяется только локальная переменная dest.

...