Hi everybody. There is a small C program. It does HTML formatting, not yet completely. Here is the code itself.

#include <stdio.h> #include <malloc.h> #include <stdbool.h> #include <string.h> #include <math.h> #define SIZE_OF_STR 1024 #define SIZE_OF_ARR_COL 128 char **div_format(char **s); // <div> cheburashka <div> pozdno el kofe i </div> slivki </div> int main() { char **s, itterator[1]; int result = 0; do { s = calloc(1, sizeof(char *)); *s = calloc(1, sizeof(char) * SIZE_OF_STR); fputs(">> Type string or 0 to exit: \n", stdout); fgets(*s, SIZE_OF_STR, stdin); if (*s == NULL) { fprintf(stdout, "\n>> Input error, press any key to exit\n"); getchar(); return EXIT_SUCCESS; } else { itterator[0] = **s; if (**s != '0') { fprintf(stdout, "\n\n<< Input: %s<< Address: %p\n", *s, &*s); result = (int) div_format(s); fputs("\n\n", stdout); free(s); free(*s); } } } while (itterator[0] != '0'); return result; } char **div_format(char **s) { char *str = *s, **tags, **texts, *out; char textholder[15] = "{{textholder}}"; int i = 0, j = 0, p = 0; bool checked = false; tags = (char **) calloc(SIZE_OF_STR, sizeof(char *)); texts = (char **) calloc(SIZE_OF_STR, sizeof(char *)); out = (char *) calloc(SIZE_OF_ARR_COL, sizeof(char)); for (int l = 0; l < SIZE_OF_STR; ++l) { tags[l] = (char *) calloc(1, sizeof(char) * SIZE_OF_ARR_COL); texts[l] = (char *) calloc(1, sizeof(char) * SIZE_OF_ARR_COL); } while (str[i] != '\0') { if (str[i] == ' ' && checked == false) { while (str[i] == ' ') i++; checked = true; } if (str[i] == '<') { int k = 0; while (str[i] != '>' && str[i] != '\0' && str[i] != '\n') { if (k == 0) { tags[j][k] = '\n'; k++; } else { if (k != 1 && str[i] == '<') { k++; break; } tags[j][k] = str[i]; if (str[i + 1] == '>') { tags[j][k + 1] = str[i + 1]; } i++; k++; } } j++; } else { int k = 0; while ((k == 0 || str[i] != ' ') && str[i] != '\0') { if (str[i] != '\n') texts[p][k] = str[i]; else { p--; break; } i++; k++; } if (j != 0) strcat(tags[j - 1], textholder); p++; } i++; } fputs("\n", stdout); for (int m = 0; m < j; ++m) { fprintf(stdout, "<< Tags: %s\tAdress: %p\n", tags[m], &tags[m]); strcat(out, tags[m]); } fputs("\n", stdout); for (int n = 0; n < p; ++n) { fprintf(stdout, "<< Texts: %s\tAdress: %p\n", texts[n], &texts[n]); } fprintf(stdout, "\n<< Formatted input: %s\n<< Formatted address: %p\n<< Length: %d\n", out, &out, i); for (int w = 0; w < SIZE_OF_STR; ++w) { free(texts[w]); free(tags[w]); } free(str); free(texts); free(tags); free(out); free(s); return EXIT_SUCCESS; } 

The comments contain a verification phrase. The problem is that if you just enter a verification phrase, then everything is fine. But if you enter it twice (that is, to make it like this: <div> cheburashka <div> pozdno el kofe i </div> slivki </div><div> cheburashka <div> pozdno el kofe i </div> slivki </div> ), the program crashes. If you remove all the free() function div_format() , then you can copy and paste as much as you like, it will not crash. The problem is clearly related to memory management.

Also, I will be glad if you point out software bugs. Thank.

PS Error disappeared while recalculating constants.

  • 2
    free(s); free(*s); Ub for sure. - pavel
  • @pavel agree, but still not the root of the problem - David Arutiunian
  • one
    You have 2 times free of the same memory. One at the end of div_format(char **s) (free (s)), and the other in main after calling div_format(s); too free (s) - avp

1 answer 1

There are two mistakes

1. as mentioned above in comments - double release of s and * s occurs. the second release is worth removing from div_format ()

 //free(str); free(texts); free(tags); free(out); //free(s); 

2. The constants are confused here. At the beginning of the div_format () function, first an array of pointers to strings is allocated, and then in the loop, the strings themselves are selected.

I suppose there should be SIZE_OF_ARR_COL rows, and each row should be the size of SIZE_OF_STR.

And in your source code, SIZE_OF_STR (1024) rows of length SIZE_OF_ARR_COL (128) each stand out. The program seems to crash when an attempt is made to write a string longer than 128 characters (128 lines of memory are allocated for lines)

If you swap constants, then everything works without segfault:

 //tags = (char **) calloc(SIZE_OF_STR, sizeof(char *)); //texts = (char **) calloc(SIZE_OF_STR, sizeof(char *)); //out = (char *) calloc(SIZE_OF_ARR_COL, sizeof(char)); tags = (char **) calloc(SIZE_OF_ARR_COL, sizeof(char *)); texts = (char **) calloc(SIZE_OF_ARR_COL, sizeof(char *)); out = (char *) calloc(SIZE_OF_STR, sizeof(char)); //for (int l = 0; l < SIZE_OF_STR; ++l) { // tags[l] = (char *) calloc(1, sizeof(char) * SIZE_OF_ARR_COL); // texts[l] = (char *) calloc(1, sizeof(char) * SIZE_OF_ARR_COL); //} for (int l = 0; l < SIZE_OF_ARR_COL; ++l) { tags[l] = (char *) calloc(1, sizeof(char) * SIZE_OF_STR); texts[l] = (char *) calloc(1, sizeof(char) * SIZE_OF_STR); } ... //for (int w = 0; w < SIZE_OF_STR; ++w) { // free(texts[w]); // free(tags[w]); //} for (int w = 0; w < SIZE_OF_ARR_COL; ++w) { free(texts[w]); free(tags[w]); } ... //free(str); free(texts); free(tags); free(out); //free(s); 

PS

You should also change the order of freeing the array s:

 free(*s); free(s); 

(at first the line is released, and then the pointer to the line). Otherwise there is a risk of seg fault in this place.

  • The main error of the vehicle is 2 times free for memory, which it receives in the main right here - do { s = calloc(1, sizeof(char *)); ... do { s = calloc(1, sizeof(char *)); ... - avp
  • Yes, I agree, and this one too. I'll fix the main answer now. - Peter K.
  • Thank you, I made all the changes and everything works - David Arutiunian