为什么当我对 char** 执行经典包裹时出现长字符串会使程序崩溃

why long strings when i do a clasic parcel to a char** crash the program

我在使用 C 语言的这个程序时遇到了一个罕见的问题,我真的不明白为什么我在输入长字符串时会崩溃,我认为这可能是函数 strtok 但我真的不知道不知道为什么?

这里是main我测试过的最小复制代码:

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

char **str_split(char *a_str, const char a_delim) {
    char **result    = 0;
    size_t count     = 0;
    char *tmp        = a_str;
    char *last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp) {
        if (a_delim == *tmp) {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = malloc(sizeof(char *) * count);

    if (result) {
        size_t idx  = 0;
        char *token = strtok(a_str, delim);

        while (token) {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }
    return result;
}

char ***text_to_array(char *path) {
    //Inputs T01/comprobar_senales/ctrlc_small.txt
    char *palabra = path;
    printf("%s", palabra);
    FILE *fp = fopen(palabra, "r");
    if (fp == NULL) {
        perror("Unable to open file!");
        exit(1);
    }

    //contador
    int ch = 0;
    int lines = 0;
    while (!feof(fp)) {
        ch = fgetc(fp);
        if (ch == '\n') {
            lines++;
        }
    }
    lines++;
    fclose(fp);
    printf("numb of lines ");
    printf("%d\n", lines);
    //contador

    fp = fopen(palabra, "r");   
    char chunk[255];//recordar mejor este lector

    char ***list_with_text = malloc(lines * sizeof(char**));
    //char list_with_text[lines];

    // Store the chunks of text into a line buffer
    int count_of_lines = 0;
    size_t len = sizeof(chunk);
    char *line = malloc(len);
    char *aux_line = malloc(len);
    char **aux_for_split;
    if (line == NULL) {
        perror("Unable to allocate memory for the line buffer.");
        exit(1);
    }

    // "Empty" the string
    line[0] = '[=10=]';

    while (fgets(chunk, sizeof(chunk), fp) != NULL) {
        // Resize the line buffer if necessary
        size_t len_used = strlen(line);
        size_t chunk_used = strlen(chunk);

        if (len - len_used < chunk_used) {
            len *= 2;
            if ((line = realloc(line, len)) == NULL) {
                perror("Unable to reallocate memory for the line buffer.");
                free(line);
                exit(1);
            }
        }
        // Copy the chunk to the end of the line buffer
        strncpy(line + len_used, chunk, len - len_used);
        len_used += chunk_used;
        fputs(line, stdout);
        strcpy(aux_line, line);
        aux_for_split = str_split(aux_line, ' ');
        list_with_text[count_of_lines] = aux_for_split; //char**
        count_of_lines++;
        // Check if line contains '\n', if yes process the line of text
        if (line[len_used - 1] == '\n') {
            printf("%d", strlen(line));
            fputs("|*\n", stdout);
            // "Empty" the line buffer
            line[0] = '[=10=]';
        } else {
            fputs(line, stdout);
        }
    }

    fclose(fp);
    free(line);
    //printf(list_with_text);
    printf("\nMax line size: %d\n", len);

    return list_with_text;
}

char ***text_to_array(char *);

int main(int argc, char *argv[]) {
    char ***texto_en_lista = text_to_array("input.txt");
    printf("%s\n", texto_en_lista[0][0]);
    printf("bye");
}

我试过这个输入:

3
IchottMano 0 400 9 9 8 7 7 2 2 4 7 6 2 2 8 5 2 5 10 8 7 9 9 7 8 2 9 1 2 8 9 4 1 3 4 7 3 1 3 5 4 3 2 2 9 5 2 9 1 9 10 4 2 7 5 4 8 5 8 3 9 9 7 2 6 4 4 8 5 4 4 3 7 2 6 5
Jaluco 100 300 7 1 2 3 3 7 1 1 7 2 9 6 3 5 4 9 6 8 2 2 8 3 5 8 9 7 5 5 9 4 3 4 9 1 9 7 2 2 9 10 2 10 3 4 1 1 10 5 1 10 4 9 1 6 5 7 2 8 10 3 9 4 2 2 2 1 9 2 7 6 7 10 7 2 4 4 10 7 7 2 3 5 9 3 7 2 7 5 9 2 1 4 8 3 1 4 5 6 5 4 5 5 8 1 9 3 1 8 9 6 6 7 2 8
Mtenis96 200 500 7 9 5 9 2 4 3 8 10 9 2 3 9 7 2 4 8 7 1 1 7 4 3 9 9 6 5 7 10 2 10 7 5 3 2 6 10 10 4 5 4 7 8 3 2 6 10 10 1 4 2 2 2 6 9 2 4 8 5 2 10 9 3 9 8 7 3 2 1 4 2 4 7 8 4 6 9 4 3 9 4 5 2 1 1 2 6 6 4 3 7 4 7 3 4 5 6 5 4 5 5 8 1 9 3 1 8 9 6 6 7 2 8 1 2 3 4 1 2 3 4 1 2 3

我唯一的线索是,如果我在这个输入的最后一行添加一个数字(space,然后是一个数字)程序崩溃,执行没有给我更多除此 window:

之外的崩溃信息

终于修复了这个错误,只是我更改了函数位置的一些代码 text_to_array:

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

char** str_split(char* a_str, const char a_delim)
{
    char** result    = 0;
    size_t count     = 0;
    char* tmp        = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = malloc(sizeof(char*) * count);

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);

        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    return result;
}


char ***text_to_array(char *path){

    char *palabra = path;
    FILE *fp = fopen(palabra, "r");
    if(fp == NULL) {
        perror("Unable to open file!");
        exit(1);
    }

    //contador de lineas
    int ch = 0;
    int lines = 0;
    while(!feof(fp))
    {
        ch = fgetc(fp);
        if(ch == '\n')
        {
            lines++;
        }
    }
    lines++;
    fclose(fp);
    //contador de lineas
    printf("numero de lineas %d",lines);
    fp = fopen(palabra, "r");   
    char chunk[255];
    char ***list_with_text = malloc(lines*sizeof(char**));
    int i;  
    // Store the chunks of text into a line buffer
    int count_of_lines = 0;
    size_t len = sizeof(chunk);
    char *line = malloc(len);
    char *aux_line = malloc(len);
    char **aux_for_split;
    // "Empty" the string
    line[0] = '[=10=]';
    printf("empezo el webeo mierd222a");
    while(fgets(chunk, sizeof(chunk), fp) != NULL) {
        size_t len_used = strlen(line);
        size_t chunk_used = strlen(chunk);
        if(len - len_used < chunk_used) {
            len *= 2;
            //printf("agrandando buffer \n");
            if((line = realloc(line, len)) == NULL) {
                perror("Unable to reallocate memory for the line buffer.");
                free(line);
                exit(1);
            }
        }  
        // Copy the chunk to the end of the line bufferr
        strncpy(line + len_used, chunk, len - len_used);
        len_used += chunk_used;
        //all that it was here now i did in the next if
        if(line[len_used - 1] == '\n') {
            aux_line = realloc(aux_line,len);//HERE is where i put all the past code to have a dinamic reader
            strcpy(aux_line,line);//HERE is where i put all the past code to have a dinamic reader
            list_with_text[count_of_lines]=str_split(aux_line,' ');//HERE is where i put all the past code to have a dinamic reader
            count_of_lines++;//HERE is where i put all the past code to have a dinamic reader
            line[0] = '[=10=]';   
        }else{

        }        
    }
    fclose(fp);
    free(line);
    printf("\nMax line size: %d\n", len);
    return list_with_text;  
}




char ***text_to_array(char*);
int main(int argc, char *argv[]) {
    char ***texto_en_lista = text_to_array("input.txt");
    printf("%s\n", texto_en_lista[0][0]);
    printf("bye");
}

问题出在这部分代码中:

aux_line = realloc(aux_line,len);//HERE is where i put all the past code to have a dinamic reader
                strcpy(aux_line,line);//HERE is where i put all the past code to have a dinamic reader
                list_with_text[count_of_lines]=str_split(aux_line,' ');//HERE is where i put all the past code to have a dinamic reader
                count_of_lines++;//HERE is where i put all the past code to have a dinamic reader

因为我一直在写变量,该变量包含我从文件中提取的 tge 数据的不同部分的所有缓冲区(255 是缓冲区的大小,换句话说,我的字符数量提取文件以将其保存在其他 var 中以读取所有行)