-2

I have this program. When I run in on gcc using gcc egyptionFractions.c -o egypt -Wall -std=c11, it works great! However, I am trying to run it using llvm on a server and I continually get this error:

* Error in `/home/codewarrior/solution': malloc(): memory corruption (fast): 0x0000000000fb8620 *

The program uses malloc and realloc several times, but I can't find the issue. I think maybe a null string end may run off the memory, but when I increase the allocation size, my answers go off track...

The function is given two numbers, like "3" and "4". It decomposes the fraction in a greedy mannor like "1/2 + 1/4". You can see the sample input and output at the bottom.

I really appreciate your help. Again, it runs perfectly on gcc. :) And I don't have an llvm compiler.. I looked through some of the other threads concerning similar issues and haven't found an acceptable solution.

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

char* decompose(char* nrStr, char* drStr) {
  long long num = atof(nrStr);
  long long den = atof(drStr);
  double val = 1.0 * num / den;

  int curr_den = 2, curr_pos = 0;
  char * ans = malloc(1);
  ans[0] = 0;
  char denStr[50] = {0};

  if (val > 1)
  {
      sprintf(denStr, "%lld,", num/den);
      num -= (int)val * den;
      ans = realloc(ans, curr_pos += strlen(denStr) );
      strcat(ans, denStr);
  }
  printf("strlen:  %d\n", (int)strlen(denStr));
  while (num > 0)
  {
      if (1.0*num/den >= 1.0/curr_den)
      {
        num *= curr_den;
        if (num >= den)
        {
            num -= den;
            sprintf(denStr, "1/%d,", curr_den);
            ans = realloc(ans, curr_pos += strlen(denStr) );
            printf("strlen:  %d\n", (int)strlen(denStr));

            strcat(ans, denStr);
        }
        den *= curr_den;
      }
      curr_den++;
  }
  ans[curr_pos-1] = '\0';
  return ans;
}

void dotest(char* u, char* v, char* expr) {
    char* sact = decompose(u, v);
    if(strcmp(sact, expr) != 0)
        printf("Error. Expected %s but got %s\n", expr, sact);
    printf("%s\n%s\n\n", sact, expr);
    free(sact); sact = NULL;
}

int main () {

    dotest("3", "4", "1/2,1/4");
    dotest("12","4", "3");
    dotest("4","5", "1/2,1/4,1/20");
    dotest("66","100", "1/2,1/7,1/59,1/5163,1/53307975");
    dotest("22","23", "1/2,1/3,1/9,1/83,1/34362");
    //dotest("99","101", "1/2,1/3,1/7,1/250,1/132563");
    return 0;
}
Ryan
  • 436
  • 5
  • 15
  • 1
    *Again, it runs perfectly on gcc.* No, it *appears* to run perfectly on GCC. It likely *doesn't*. It just doesn't actually emit an error. – Andrew Henle Apr 27 '17 at 13:14
  • 2
    `ans = realloc(ans, curr_pos += strlen(denStr) );`might be a bit too small ... – wildplasser Apr 27 '17 at 13:16
  • Since You know the compiler, maybe it's time to meet the debugger? – riodoro1 Apr 27 '17 at 13:20
  • 2
    Since you already know `sprintf()`, maybe it's time to meet `snprintf()` ? – wildplasser Apr 27 '17 at 13:29
  • Hey, that's a really good idea. I'm doing these little projects to learn C better. – Ryan Apr 27 '17 at 13:34
  • `char * ans = malloc(1);` looks fishy. – Jabberwocky Apr 27 '17 at 13:44
  • I think you have to malloc before you can realloc. So I did that just to allocate a null string. – Ryan Apr 27 '17 at 13:46
  • @Ryan Actually `char * ans = malloc(1);` is OK, but it's not needed, you can realloc a `NULL` pointer. See [`realloc` documentation](http://en.cppreference.com/w/c/memory/realloc) – Jabberwocky Apr 27 '17 at 13:51
  • `I think you have to malloc before you can realloc.` You are wrong. `realloc(NULL, new_size);` works just like `malloc(new_size);` It is all in The Fine Manual. – wildplasser Apr 27 '17 at 13:55
  • @MichaelWalz I get really weird results when I take it out. even if I null terminate after the first realloc, I see junk data all over. – Ryan Apr 27 '17 at 13:56
  • @Ryan you can't just take it out of course, this would leave `ans` uninitialized, you need to replace it by `char * ans = NULL;`. – Jabberwocky Apr 27 '17 at 14:00
  • When I replace it with NULL, I get weird results. Junk data on terminal. – Ryan Apr 27 '17 at 14:02
  • You don't check for errors, which is a very bad idea. `ans = realloc(ans, ...=` is also a no-go; what if `realloc` returns a null-pointer? You loose the original pointer. – too honest for this site Apr 27 '17 at 14:02

1 Answers1

0

The solution is... after I decoupled these two statements, then add 1 to allocation..

    curr_pos += strlen(denStr);
    ans = realloc(ans, curr_pos+1 );

I was doing this:

        ans = realloc(ans, curr_pos += strlen(denStr)+1 );

Which broke things! I post on here and then the answer comes too quick. Sorry if I wasted anyone's time!

Ryan
  • 436
  • 5
  • 15