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.