Freeing up memory with free function causing my program to crash - c

I could use some help with my program,
I wrote a program that is counting the number of anagrams in a sentence, for which I am using a malloc() function, you can see in my code **ArrPtr=malloc.
I use this to count the anagrams, after finishing it I want to continue to my second part of the program and I wish to free the memory with free(arrPtr);
and the program crashes (It didn't crash when I did not use the free option).
Here's my code,
void main()
{
char str[1001] = { 0 };
char temp[1001] = { 0 }, temp2;
char strB[1001] = { 0 };
int printf_i, counter, i, q, flag, j = 1, r = 0, m = 1, length = 0, root = 0, m1 = 0;
int max_analogy = 0, counter2 = 0, O, sum, sum2;
char **arrPtr;
int k = 0;
int **matrix;
printf("Please enter the sentence, and then press Enter:\n");
gets(str);
//bubble sort
strcpy_s(strB, 1001, str);
for (i = 0; i < strlen(strB); i = q + 2)
{
do
{
flag = 0;
for (q = i; strB[q + 1] != 32 && strB[q + 1] != 0; q++)
{
if (strB[q] > strB[q + 1])
{
// Swap
temp2 = strB[q];
strB[q] = strB[q + 1];
strB[q + 1] = temp2;
flag = 1;
}
}
} while (flag != 0);
}
counter = 1;
length = strlen(strB);
for (i = 0; strB[i] != 0; i++)
{
if (strB[i] == 32)
{
strB[i] = 0;
counter++;
}
}
arrPtr = (char*)malloc(sizeof(char)*counter);
arrPtr[0] = strB;
q = 1;
for (i = 0; i < length - 1; i++)
{
if (strB[i] == 0)
{
arrPtr[q] = &strB[i + 1];
q++;
}
}
counter2 = 0;
for (i = 0; i < counter; i++)
{
for (q = i + 1; q < counter; q++)
{
if (arrPtr[q] == 0 || arrPtr[i] == 0)
continue;
if (!strcmp(arrPtr[q], arrPtr[i]))
{
counter2++;
arrPtr[q] = 0;
}
}
if (max_analogy < counter2)
max_analogy = counter2;
counter2 = 0;
}
printf("The maximum number of anagram words in this sentence is %d.\n", max_analogy);
free(arrPtr);
}

arrPtr = (char*)malloc(sizeof(char)*counter);
is wrong fo many reason:
arrPtr is (char **).
cast using a C compiler is useless and dangerous.
you must allocate sizeof(char *)
reason 3 is the real reason of you problem: you are allocating counter bytes while you write counter*sizeof(char *) (most probably counter*8), so you are writing out of bounds of allocated memory corrupting malloc memory pool.
You can fix it using
arrPtr = malloc(sizeof(char *)*counter);

Related

I wrote a code to print the union and intersection of two strings sets. I allocated memory in some parts.The last part is not working properly

The last part of the code where I am allocating memory to common_set is not working whereas other mallocs worked fine above. Similarly when I freed the unique_set for the third time it is not done properly. I am not able to get the printf sentences which I wrote after them. I am not able to free the pointer of the union_set. Also I am not able to allocate memory to a new pointer common_pointer.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
void dict(char **str, int man, int MAY) {
char temp[MAY];
for (int i = 0; i < man; ++i) {
for (int j = i + 1; j < man; ++j) {
if (strcmp(str[i], str[j]) > 0) {
strcpy(temp, str[i]);
strcpy(str[i], str[j]);
strcpy(str[j], temp);
}
}
}
}
//int k = 0;
char **unique_set;
char **a_new_sumset;
int unique(char **s, int l, int d, int k) {
if (d == l) {
unique_set[k] = (char*)malloc((strlen(s[l]) + 1) * sizeof(char));
strcpy(unique_set[k], s[l]);
return k;
} else {
for (int i = l; i < d; i++) {
if (strcmp(s[i], s[i + 1]) == 0 && i + 1 == d) {
unique_set[k] = (char*)malloc((strlen(s[i + 1]) + 1) * sizeof(char));
strcpy(unique_set[k], s[i + 1]);
return k;
//printf("demo: %s\n", unique_set[k]);
} else
if (strcmp(s[i], s[i + 1]) != 0) {
unique_set[k] = (char*)malloc((strlen(s[i]) + 1) * sizeof(char));
strcpy(unique_set[k], s[i]);
//printf("demo1: %s\n", unique_set[k]);
k++;
unique(s, i + 1, d, k);
break;
}
}
}
}
char **common_set;
char **intersection(char **sum_set, int d) {
int k = 0;
for (int i = 0; i < d; i++) {
if (strcmp(sum_set[i], sum_set[i + 1]) == 0 && strcmp(sum_set[i], sum_set[i + 2]) != 0 && i + 2 < d) {
common_set[k] = (char*)malloc((strlen(sum_set[i]) + 1) * sizeof(char));
strcpy(common_set[k], sum_set[i]);
k++;
} else
if (strcmp(sum_set[i], sum_set[i + 1]) == 0 && i + 2 > d) {
common_set[k] = (char*)malloc((strlen(sum_set[i]) + 1) * sizeof(char));
strcpy(common_set[k], sum_set[i]);
k++;
}
}
return common_set;
}
#define maxx1 3 // number of words in grp 1
#define maxy1 10 // word limit for the first group of words
#define maxx2 3 // number of words in grp2
#define maxy2 10 // word limit for the next group of words
int main() {
char **sum_set;
char **str_g1;
char **str_g2;
char words1[maxy1];
str_g1 = (char**)malloc(maxx1 * sizeof(char*));
char words2[maxy2];
str_g2 = (char**)malloc(maxx2 * sizeof(char*));
printf("Enter the first group:\n");
for (int i = 0; i < maxx1; i++) {
gets(words1);
str_g1[i] = (char*)malloc((strlen(words1) + 1) * sizeof(char));
strcpy(str_g1[i], words1);
//puts(ptr[i]);
//printf("%d", i);
}
printf("Enter the second group:\n");
for (int i = 0; i < maxx2; i++) {
gets(words2);
str_g2[i] = (char*)malloc((strlen(words2) + 1) * sizeof(char));
strcpy(str_g2[i], words2);
//puts(ptr[i]);
//printf("%d", i);
}
dict(str_g1, maxx1, maxy1); //to lexicographically arrange the string 1 group
dict(str_g2, maxx2, maxy2);
sum_set = (char**)malloc((maxx1 + maxx2) * sizeof(char*));
a_new_sumset = (char**)malloc((maxx1 + maxx2) * sizeof(char*));
for (int i = 0; i < maxx1; i++) {
sum_set[i] = (char*)malloc((strlen(str_g1[i]) + 1) * sizeof(char));
strcpy(sum_set[i], str_g1[i]);
//puts(sum_set[i]);
}
for (int i = 0; i < maxx2; i++) {
sum_set[i + maxx1] = (char*)malloc((strlen(str_g2[i]) + 1) * sizeof(char));
strcpy(sum_set[i + maxx2], str_g2[i]);
//puts(sum_set[i + maxx1]);
}
dict(sum_set, maxx1 + maxx2, maxy1 + maxy2);
unique_set = (char**)malloc((maxx1) * sizeof(char*));//allocating memory to next string group to compute its set
int k = unique(str_g1, 0, maxx1 - 1, 0);
printf("%d \n", k);
printf("The set of the string A in arranged order is:\n");
for (int i = 0; i <= k; i++) {
a_new_sumset[i] = (char*)malloc((strlen(unique_set[i]) + 1) * sizeof(char));
strcpy(a_new_sumset[i], unique_set[i]);
puts(unique_set[i]);
//
}
//printf("freed the pointers\n");
for (int i = 0; i <= k; ++i) {//freeing the arrays
free(unique_set[i]);
}
free(unique_set);
//printf("freed the pointers\n");//freeing the top pointer
int a = k;
unique_set = (char**)malloc((maxx2) * sizeof(char*));//allocating memory to next string group to compute its set
k = unique(str_g2, 0, maxx2 - 1, 0);
int b = k;
printf("The set of the string B in arranged order is:\n");
for (int i = 0; i <= k; i++) {
a_new_sumset[i + 1 + a] = (char*)malloc((strlen(unique_set[i]) + 1) * sizeof(char));
strcpy(a_new_sumset[i + a + 1], unique_set[i]);
puts(unique_set[i]);
//strcpy(a_new_sumset[i + a + 1], unique_set[i]);
}
printf("%d \n", k);
for (int i = 0; i <= k; ++i) {//freeing the arrays
free(unique_set[i]);
}
free(unique_set);//freeing the top pointer
printf("freed the pointers\n");
unique_set = (char**)malloc((a + b) * sizeof(char*));//allocating memory to unique_set for computing the union of the sets
k = unique(sum_set, 0, (maxx1 + maxx2) - 1, 0);
printf("The set of the string A+B in arranged order is:\n");
for (int i = 0; i <= k; i++)
puts(unique_set[i]);
for (int i = 0; i <= k; ++i) {//freeing the arrays
free(unique_set[i]);
}
printf("freed the pointers\n");
free(unique_set);
printf("freed the pointers\n");
printf("The intersection_set of the string A+B in arranged order is:\n");
common_set = (char**)malloc((maxx1 + maxx2) * sizeof(char*));
printf("The intersection_set of the string A+B in arranged order is:\n");
char **p;
p = intersection(a_new_sumset, (maxx1 + maxx2) - 1);
printf("The intersection_set of the string A+B in arranged order is:\n");
for (int i = 0; i <maxx1 + maxx2; i++) {
puts(p[i]);
}
}
There are many issues in the code:
in function dict, you should not copy the strings, but swap the pointers instead, which is simpler and works for any string length. Furthermore the name dict is confusing for this function, prefer a more informative name such as sort_strings:
void sort_strings(char **str, int man) {
for (int i = 0; i < man; ++i) {
for (int j = i + 1; j < man; ++j) {
if (strcmp(str[i], str[j]) > 0) {
char *temp = str[i];
str[i] = str[j];
str[j] = temp;
}
}
}
}
global variables are not necessary for this task, prefer local variables, pass destination arrays as arguments and return the number of strings as the return value.
the string allocation code is duplicated everywhere... using the strdup() function or a wrapper that tests for memory allocation failure would improve readability.
avoid variable name l, which looks confusingly similar to 1
the uniq function does not return a value in the else branch, it is unclear what it does and why it is recursive.
the loop to add the strings from the second group has a bug: strcpy(sum_set[i + maxx2], str_g2[i]); should be strcpy(sum_set[i + maxx1], str_g2[i]);. This mistake has no effect now because maxx1 == maxx2 but should be fixed.
in function intersection, you compare strings at offset d + 1 and d + 2 before testing if these index values are within the array boundaries.
selecting duplicated strings in intersection makes the assumption that strings are not duplicated in group 1 and 2.
the number of common strings is not returned, nor stored into a global variable, so main() cannot determine this number and uses maxx1 + maxx2 which is always wrong for non trivial cases.
Here is a modified version using functions to read lines, sort an array, find unique values, compute the union and intersection of sets and free the string arrays:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// allocate a copy of a string or die
char *xstrdup(const char *str) {
char *p = strdup(str);
if (p == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
return p;
}
// read a line of at most max bytes
char *get_line(int max) {
char buf[max + 1];
int i = 0;
int c;
while ((c = getchar()) != EOF && c != '\n') {
if (i < max) {
buf[i++] = (char)c;
}
}
buf[i] = '\0';
return xstrdup(buf);
}
// free the strings in an array of size n
void free_strings(char **strings, int n) {
for (int i = 0; i < n; i++) {
free(strings[i]);
}
}
// copy strings in lexicographical order
int sort_strings(char **sorted, char **str, int n) {
int i, j;
for (i = 0; i < n; i++) {
for (j = i; j > 0 && strcmp(sorted[j - 1], str[i]) > 0; j--) {
sorted[j] = sorted[j - 1];
}
sorted[j] = xstrdup(str[i]);
}
return n;
}
// copy unique strings in lexicographical order
int uniq_strings(char **unique_strings, char **strings, int n) {
int i, k = 0;
for (i = 0; i < n; i++) {
if (i == 0 || strcmp(strings[i - 1], strings[i]) != 0) {
unique_strings[k++] = xstrdup(strings[i]);
}
}
return k;
}
int intersection_strings(char **intersection_set, char **str1, int n1, char **str2, int n2) {
int i = 0, j = 0, k = 0;
while (i < n1 && j < n2) {
int c = strcmp(str1[i], str2[j]);
if (c < 0) {
i++;
} else
if (c > 0) {
j++;
} else {
intersection_set[k++] = xstrdup(str1[i]);
i++;
j++;
}
}
return k;
}
int union_strings(char **union_set, char **str1, int n1, char **str2, int n2) {
int i = 0, j = 0, k = 0;
while (i < n1 && j < n2) {
int c = strcmp(str1[i], str2[j]);
if (c < 0) {
union_set[k++] = xstrdup(str1[i]);
i++;
} else
if (c > 0) {
union_set[k++] = xstrdup(str2[j]);
j++;
} else {
union_set[k++] = xstrdup(str1[i]);
i++;
j++;
}
}
while (i < n1) {
union_set[k++] = xstrdup(str1[i++]);
}
while (j < n2) {
union_set[k++] = xstrdup(str2[j++]);
}
return k;
}
void print_set(char **set, int n, const char *desc) {
if (desc) {
printf("%s", desc);
}
for (int i = 0; i < n; i++) {
puts(set[i]);
}
}
#define maxx1 3 // number of words in grp 1
#define maxy1 10 // word limit for the first group of words
#define maxx2 3 // number of words in grp2
#define maxy2 10 // word limit for the second group of words
int main() {
char *str_g1[maxx1];
char *str_s1[maxx1];
char *str_u1[maxx1];
char *str_g2[maxx2];
char *str_s2[maxx2];
char *str_u2[maxx2];
char *union_set[maxx1 + maxx2];
char *intersection_set[maxx1 < maxx2 ? maxx1 : maxx2];
printf("Enter the first group:\n");
for (int i = 0; i < maxx1; i++) {
str_g1[i] = get_line(maxy1);
}
printf("Enter the second group:\n");
for (int i = 0; i < maxx2; i++) {
str_g2[i] = get_line(maxy2);
}
sort_strings(str_s1, str_g1, maxx1);
int n1 = uniq_strings(str_u1, str_s1, maxx1);
sort_strings(str_s2, str_g2, maxx1);
int n2 = uniq_strings(str_u2, str_s2, maxx2);
print_set(str_u1, n1, "The set of the string A in arranged order is:\n");
print_set(str_u2, n2, "The set of the string B in arranged order is:\n");
// compute union and intersection
int nu = union_strings(union_set, str_u1, n1, str_u2, n2);
int ni = intersection_strings(intersection_set, str_u1, n1, str_u2, n2);
print_set(union_set, nu, "The set of the string A+B in arranged order is:\n");
print_set(intersection_set, ni, "The intersection_set of the string A*B in arranged order is:\n");
free_strings(str_g1, maxx1);
free_strings(str_g2, maxx2);
free_strings(str_s1, maxx1);
free_strings(str_s2, maxx2);
free_strings(str_u1, n1);
free_strings(str_u2, n2);
free_strings(union_set, nu);
free_strings(intersection_set, ni);
return 0;
}
To improve on this code, you can define a structure string_set to combine the string array along with variables describing its allocated size and active count. Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct string_set {
int count, size;
char **array;
} string_set;
// allocate a copy of a string or die
char *xstrdup(const char *str) {
char *p = strdup(str);
if (p == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
return p;
}
void *xalloc(size_t n) {
void *p = malloc(n);
if (p == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
return p;
}
string_set *string_set_allocate(int size) {
string_set *set = xalloc(sizeof(*set));
set->count = 0;
set->size = size;
set->array = xalloc(sizeof(*set->array) * size);
return set;
}
void string_set_free(string_set *set) {
while (set->count --> 0) {
free(set->array[set->count]);
}
free(set->array);
free(set);
}
// read a line of at most max bytes
char *get_line(int max) {
char buf[max + 1];
int i = 0;
int c;
while ((c = getchar()) != EOF && c != '\n') {
if (i < max) {
buf[i++] = (char)c;
}
}
buf[i] = '\0';
return xstrdup(buf);
}
string_set *string_set_clone(string_set *set) {
string_set *copy = string_set_allocate(set->size);
for (int i = 0; i < set->count; i++) {
copy->array[i] = xstrdup(set->array[i]);
}
copy->count = set->count;
return copy;
}
void string_set_sort(string_set *set) {
for (int i = 0; i < set->count; i++) {
for (int j = i + 1; j < set->count; j++) {
if (strcmp(set->array[i], set->array[j]) > 0) {
char *temp = set->array[i];
set->array[i] = set->array[j];
set->array[j] = temp;
}
}
}
}
void string_set_uniq(string_set *set) {
if (set->count > 0) {
int j = 1;
for (int i = 1; i < set->count; i++) {
if (strcmp(set->array[i], set->array[j - 1]) == 0) {
free(set->array[i]);
set->array[i] = NULL;
} else {
set->array[j++] = set->array[i];
}
}
set->count = j;
}
}
string_set *string_set_intersection(string_set *set1, string_set *set2) {
int n1 = set1->count;
int n2 = set2->count;
string_set *res = string_set_allocate(n1 < n2 ? n1 : n2);
int i = 0, j = 0, k = 0;
while (i < n1 && j < n2) {
int c = strcmp(set1->array[i], set2->array[j]);
if (c < 0) {
i++;
} else
if (c > 0) {
j++;
} else {
res->array[k++] = xstrdup(set1->array[i]);
i++;
j++;
}
}
res->count = k;
return res;
}
string_set *string_set_union(string_set *set1, string_set *set2) {
int n1 = set1->count;
int n2 = set2->count;
string_set *res = string_set_allocate(n1 + n2);
int i = 0, j = 0, k = 0;
while (i < n1 && j < n2) {
int c = strcmp(set1->array[i], set2->array[j]);
if (c < 0) {
res->array[k++] = xstrdup(set1->array[i]);
i++;
} else
if (c > 0) {
res->array[k++] = xstrdup(set2->array[j]);
j++;
} else {
res->array[k++] = xstrdup(set1->array[i]);
i++;
j++;
}
}
while (i < n1) {
res->array[k++] = xstrdup(set1->array[i++]);
}
while (j < n2) {
res->array[k++] = xstrdup(set2->array[j++]);
}
res->count = k;
return res;
}
void string_set_print(string_set *set, const char *desc) {
if (desc) {
printf("%s", desc);
}
for (int i = 0; i < set->count; i++) {
puts(set->array[i]);
}
}
#define maxx1 3 // number of words in grp 1
#define maxy1 10 // word limit for the first group of words
#define maxx2 3 // number of words in grp2
#define maxy2 10 // word limit for the second group of words
int main() {
string_set *str_g1 = string_set_allocate(maxx1);
string_set *str_g2 = string_set_allocate(maxx2);
printf("Enter the first group:\n");
for (int i = 0; i < maxx1; i++) {
str_g1->array[str_g1->count++] = get_line(maxy1);
}
printf("Enter the second group:\n");
for (int i = 0; i < maxx2; i++) {
str_g2->array[str_g2->count++] = get_line(maxy2);
}
string_set *str_u1 = string_set_clone(str_g1);
string_set_sort(str_u1);
string_set_uniq(str_u1);
string_set *str_u2 = string_set_clone(str_g2);
string_set_sort(str_u2);
string_set_uniq(str_u2);
string_set_print(str_u1, "The set of the string A in arranged order is:\n");
string_set_print(str_u2, "The set of the string B in arranged order is:\n");
string_set *union_set = string_set_union(str_u1, str_u2);
string_set *intersection_set = string_set_intersection(str_u1, str_u2);
string_set_print(union_set, "The set of the string A+B in arranged order is:\n");
string_set_print(intersection_set, "The intersection set of the string A*B in arranged order is:\n");
string_set_free(str_g1);
string_set_free(str_g2);
string_set_free(str_u1);
string_set_free(str_u2);
string_set_free(union_set);
string_set_free(intersection_set);
return 0;
}
The last part of the code where I am allocating memory to common_set is not working ...
The problem in this part is not the allocation, but the implementation of the intersection function. You haven't provided a means for this function to return the number of elements in the intersection set, and you haven't initialized the allocated set space - you just try to access maxx1 + maxx2 set elements, most of which are undefined. Fixing this design would be a start.

Run-Time Check Failure #2 - Stack around the variable 'chars' was corrupted

char* putNum(Node* head)
{
char* str;
int size = 0;
int index = 0;
int lastNum, count = 0;
Node* temp = head->left;
lastNum = temp->info;
while (lastNum != 0)
{
lastNum = lastNum / 10;
count++;
}
if (head->info < 0)
{
size = abs(head->info) - 1;
size *= 5 + count;
str = (char*)malloc(sizeof(char) * size);
str[0] = '-';
index++;
}
else
{
size = head->info - 1;
size *= 5 + count;
str = (char*)malloc(sizeof(char) * size);
}
for (int i = 0; i < abs(head->info); i++)
{
char chars[5];
itoa(temp->info, chars, 10);
for (int j = 0; j < strlen(chars); j++)
{
str[index++] = chars[j];
}
temp = temp->left;
}
return str;
}
hi im learing c in visual studio and im tring to make a function that take a doubly linked list with a long number and put the number in a string. the error pops in the last '}' of the function.

Element disapears while calling a function - LZW Compression

I made some research but nothing was really concerning my problem...
I'm actually trying to code LZW compression for school, and I need a function to check if an element is in my dictionnary.
However, when I'm calling this function, it tries to access to the 64th element in my dictionnary, but it has desapeared !! I checked it before the function calling, it was here !! And the worse is that I can call this element in the previous callings of the function.
Could you help me please ?
The function :
int is_in_dictionnary(dico * p_pRoot, char * p_string){
int i = 0, j = 0;
char a[1024] = { 0 }, b[1024] = { 0 };
//strcpy(b, p_pRoot->m_dico[64].m_info);
for (i = 0; i < p_pRoot->m_index; i++){
printf("dico %s\n", p_pRoot->m_dico[i].m_info);
strcpy(a, p_string);
strcpy(b, p_pRoot->m_dico[i].m_info);
j = strcmp(a, b);
if (j == 0)
return i;
}
return -1;
}
The console, we are herer abble to see that the function previously called the 64th element "#", whithout any problem
The error on visual studio
Some people Asked me to add the code part where it's not functionning :
void lzw_compress(dico *p_pRoot, char * path)
{
FILE *pFile = NULL, *pCompFile = NULL;
int len_c = 0, size_tamp = 0, i = 0, masked_tamp = 0, tamp_to_write = 0, index_tamp = 0, a;
unsigned char char_tamp = 0, cAndTamp[1024] = { 0 }, tampon[1024] = { 0 }, c = '\0', temp[2] = { 0 };
char test[128] = { 0 };
pFile = fopen(path, "r+");
if (!pFile)
{
printf("problem while opening file to compress");
return;
}
size_t len = strlen(path); //creation of the output file name : paht+ ".lzw"
unsigned char *compress_name = malloc(len + 4 + 1);
strcpy(compress_name, path);
compress_name[len] = '.';
compress_name[len + 1] = 'l';
compress_name[len + 2] = 'z';
compress_name[len + 3] = 'h';
compress_name[len + 4] = '\0';
pCompFile = fopen(compress_name, "w"); //creation of the output file
free(compress_name);
while (1)
{
if (feof(pFile))
break;
c = freadByte(pFile);
for (i = 0; i < 1024; i++)
cAndTamp[i] = 0;
temp[0] = c;
strcat(cAndTamp, tampon);
strcat(cAndTamp, temp);
strcpy(test, p_pRoot->m_dico[64].m_info);
a = 0;
if (is_in_dictionnary(p_pRoot, cAndTamp) > -1)
{
strcpy(tampon, cAndTamp);
a = 0;
}
else
{
if (is_in_dictionnary(p_pRoot, tampon) < 256) //write the character in the file
{
char_tamp = tampon[0];
fwrite(&char_tamp, sizeof(char), 1, pCompFile);
a = 0;
}
else
{
a = 0;
index_tamp = is_in_dictionnary(p_pRoot, tampon);
a = 0;
for (i = 0; i < p_pRoot->m_size; i++)
{
mask = 1 << i;
masked_tamp = index_tamp & mask;
tamp_to_write = masked_tamp >> i;
fwriteBit(tamp_to_write, pCompFile);
flush(pCompFile);
}
}
strcpy(test, p_pRoot->m_dico[64].m_info); //HERE IT'S OK
add_dictionnary(p_pRoot, cAndTamp, size_tamp + 1); //add the string tamp + read byte in the dictionnay
strcpy(test, p_pRoot->m_dico[64].m_info); //HERE IT IS NOT OK
strcpy(tampon, temp);
}
strcpy(test, p_pRoot->m_dico[64].m_info);
size_tamp = is_in_dictionnary(p_pRoot, tampon);
}
if (tampon < 256) //write the character in the file
{
char_tamp = (char)tampon;
fwrite(&char_tamp, sizeof(char), 1, pCompFile);
}
else
{
index_tamp = is_in_dictionnary(p_pRoot, tampon);
for (i = 0; i < p_pRoot->m_size; i++)
{
mask = 1 << i;
masked_tamp = index_tamp & mask;
tamp_to_write = masked_tamp >> i;
fwriteBit(tamp_to_write, pCompFile);
flush(pCompFile);
}
}
fclose(pFile);
fclose(pCompFile);
}
The fucnction that where I think there is a problem
void add_dictionnary(dico * p_pRoot, char * p_string, int p_stringSize)
{
p_pRoot->m_index++;
if (p_pRoot->m_index == pow(2, p_pRoot->m_size))
realloc_dictionnary(p_pRoot);
p_pRoot->m_dico[p_pRoot->m_index].m_info = (char*)calloc(p_stringSize, sizeof(char));
strcpy(p_pRoot->m_dico[p_pRoot->m_index].m_info, p_string);
}
Another thank you guys !
I showed again the program to my teacher and he found the problem !
The problem is that i never use malloc and rarely use realloc so here was the problem :
void realloc_dictionnary(dico * p_pRoot)
{
int real = p_pRoot->m_size + 1;
int size = pow(2, real);
printf("index %d, previous pow %d, new power %d, size %d\n", p_pRoot->m_index, p_pRoot->m_size, real, size);
p_pRoot->m_dico = (code*) realloc(p_pRoot->m_dico, size);
p_pRoot->m_size = real;
}
size in a number of bits, ...
So the correction is : size * sizeof(code)!
void realloc_dictionnary(dico * p_pRoot)
{
int real = p_pRoot->m_size + 1;
int size = pow(2, real);
printf("index %d, previous pow %d, new power %d, size %d\n", p_pRoot->m_index, p_pRoot->m_size, real, size);
p_pRoot->m_dico = (code*) realloc(p_pRoot->m_dico, size * sizeof(code));
p_pRoot->m_size = real;
}
I would like to first of all say sorry because of this so little errror and also a big thanks for your great patience !

How many anagrams there are in a sentence in C

I was asked to write a code that returns the maximum number of anagrams (word made by transposing the letters of another word like the word “secure” is an anagram of “rescue.”).
This is what I did:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char text[1000], angrm1[1000], angrm2[1000];
int i, j, k, count = 1, flag = 0, temp, size = 0, q = 1, counter = 0, max = 0;
char**point;
printf_s("Please enter the sentence, and then press Enter:\n");
gets(text);
strcpy_s(angrm1, 1000, text);
j = 1; i = 0;
for (i = 0; i < strlen(angrm1); i = k + 2) {
for (k = i; angrm1[k + 1] != ' '&&angrm1[k + 1]!=0; k++) {
if (angrm1[i] > angrm1[i + 1]) {
temp = angrm1[k];
angrm1[k] = angrm1[k + 1];
angrm1[k + 1] = temp;
}
}
Blockquote Arrange the words
size = strlen(angrm1);
}
for (i = 0; angrm1[i] != 0; i++)
{
if (angrm1[i] == ' ')
{
angrm1[i] = 0;
count++;
}
}
point = (char*)malloc(sizeof(char)*count);
for (i = 0; i < (size - 1); i++)
{
if (angrm1[i] == 0)
{
point[q] = &point[i + 1];
q++;
}
}
for (i = 0; i < counter; i++)
{
for (q = i + 1; q < counter; q++)
{
if (point[q] == 0 || point[i] == 0)
continue;
if (!strcmp(point[q], point[i]))
{
counter++;
point[q] = 0;
}
}
if (max < counter)
max = counter;
counter = 0;
}
printf_s("The maximum (not yet) number of anagram words in this sentence is %d", &max);
}
The first part works (in my opinion).
But when I check with the debugger, it skips the loop and I get junk.
Can someone please help me by pointing to the problem, and explaining how to fix it?

Using realloc on a char * within an array alters data outside of that array

I'm observing some really weird behavior regarding realloc .... I was wondering if y'all could help me.
I have an array of dynamically allocated char *'s called "frags". I also have a char * called "combination" which points to some string literal that represents a new fragment. I want to replace one of the fragments within "frags" with the contents of "combination." The way my project is structured, I am sending the frags array, index of to-be-replaced frag, and combination string into a function. Within this function I have:
printf("combination before realloc: %s\n", combination);
char *newString = (char *) realloc(frags[firstIndex], strlen(combination) + 1);
assert(newString != NULL);
printf("combination after realloc: %s\n", combination);
strcpy(newString, combination);
frags[firstIndex] = newString;
Oddly, the printf's do not print the same thing. The first printf yields "hellol" which is correct, but the next printf yields jibberish - something like "{?`?p??". Thus, the problem resides in the call to realloc. And I honestly have no idea what's going on. It seems the very call to realloc has messed with combination somehow, but I thought that if that could possibly happen then it would return NULL?
Please help me :(
Edit: Adding code
bool findMaxOverlap(char *first, char *second, char **combination, int *roundMax) {
// setup lng and shrt
char *lng, *shrt;
if (strlen(first) >= strlen(second)) { lng = first; shrt = second; }
else { lng = second; shrt = first; }
int shrtLen = strlen(shrt), lngLen = strlen(lng);
// check if lng contains shrt
if (strstr(lng, shrt) != NULL && shrtLen > *roundMax) {
*combination = lng;
*roundMax = shrtLen;
return true;
}
else // check if lng's tail ends contain part of shrt
{
int numChars = shrtLen - 1, max = 0, shrtOffset = 0, lngOffset = 0;
for (int i = 0; i < shrtLen && numChars > *roundMax && numChars > max; i++) {
numChars = shrtLen - 1 - i;
for (int j = 0; j < lngLen; j++) {
if (strncmp(shrt + i, lng + j, numChars) == 0) {
max = numChars;
shrtOffset = i;
lngOffset = j;
}
}
}
if (shrtOffset > lngOffset) {
// short first
char newFrag[lngLen + shrtOffset + 1];
strncpy(newFrag, shrt, shrtOffset);
strcat(newFrag, lng + shrtOffset);
*combination = newFrag;
*roundMax = numChars;
return true;
} else {
// lng first
char newFrag[lngLen + (shrtLen - numChars) + 1];
strcpy(newFrag, lng);
strcat(newFrag, shrt + numChars);
*combination = newFrag;
printf("combination in findmax is: %s\n", *combination);
*roundMax = numChars;
return true;
}
}
return false;
}
void mergeFrags(char *frags[], int index1, int index2, char *combination) {
int firstIndex, secondIndex;
if (index1 < index2) {
firstIndex = index1;
secondIndex = index2;
} else {
firstIndex = index2;
secondIndex = index1;
}
char temp[strlen(combination) + 1];
strcpy(temp, combination);
char *newString = (char *) realloc(frags[firstIndex], strlen(combination) + 1);
assert(newString != NULL);
strcpy(newString, temp);
frags[firstIndex] = newString;
free(frags[secondIndex]);
}
char *reassemble(char *frags[], int numFrags) {
if (numFrags > 1) {
char *combination;
int max, index1, index2, currNumFrags = numFrags;
for (int currentRound = 0; currentRound < numFrags - 1; currentRound++) {
max = index1 = index2 = 0, combination = NULL;
for (int i = 0; i < currNumFrags; i++) {
for (int j = i+1; j < currNumFrags; j++) {
//find max overlap of pair
if (findMaxOverlap(frags[i], frags[j], &combination, &max)) {
printf("round #: %d, combination: %s, max: %d\n", currentRound, combination, max);
index1 = i; index2 = j;
}
}
}
// merge
mergeFrags(frags, index1, index2, combination);
currNumFrags--;
}
}
return frags[0];
}
You said (in the comments above) that you were using strdup to allocate the data in combination, but what you're really doing is setting combination to point to data that's on the stack. After findMaxOverlap returns, you are now pointing at unallocated space on the stack, and this provides you with the undefined behavior you're seeing. When realloc is called, the area in the stack is reused, and the value of combination looks like garbage.

Resources