1

I am having a rare problem with this program in C and a really don't get why I get a crash when I put long strings, I think that could be the function strtok but I really don't know why?

Here it is the main with minimal reproduced code tested by me:

#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] = '\0';

    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] = '\0';
        } 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");
}

I have tried this input:

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

and the only clue that I have is, that if I add one number (space and then a number) to the last line of this input the program crash, the execution didn't give me more information of the crash with the exception of this window:

enter image description here

chqrlie
  • 131,814
  • 10
  • 121
  • 189
mrpepo877
  • 490
  • 6
  • 23
  • 1
    What is `prefix_to_string`? – Mooing Duck May 04 '20 at 18:10
  • 3
    `while(!feof(fp))` --> [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/q/5431941/2410359) – chux - Reinstate Monica May 04 '20 at 18:15
  • Please create a [mre], i.e. a program that can be compiled and run to reproduce the problem. I suggest to copy all necessary functions to a single file. Make sure you can compile and run it yourself. The error probably results from an invalid memory access, e.g. an uninitialized pointer or an out-of-bounds access. – Bodo May 04 '20 at 18:23
  • ok i will tried to do a more simple example to give a better file :D – mrpepo877 May 04 '20 at 18:24
  • I'm trying that right now, but i had to give a variable size because i line could be even more bigger than the example – mrpepo877 May 04 '20 at 23:05

1 Answers1

1

finally this work to fix the error, only i change some code of position of the funtion 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] = '\0';
    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] = '\0';   
        }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");
}

the problem was here in this part of code:

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

because i was over writing all the time the variable that content all the buffers with diferent part of tge data that i extracted of the file (the 255 is the size of the buffer in other words the amount of char that i extract of the file to save it in other var to read a all the line)

mrpepo877
  • 490
  • 6
  • 23