C: realloc works on Linux, but not on Windows

Question

this is my first question on Stack Overflow, sorry if it's not well written. I have a little problem. I wrote a program in C (I'm currently learning C, I am a newbie, my first language, don't say I should've learnt Python, please, because I'm doing just fine with C). So, I wrote this little program. It's an attempt of mine to implement a sorting algorithm (I made the algorithm myself, with no help or documentation, it's very inefficient I think, I was just fooling around, though I don't know whether the algorithm already exists or not). The only sorting algorithm I know is QuickSort. In any case, here is the final program (has plenty of comments, to help me remember how it works if I'll ever revisit it):

// trying to implement my own sorting algorithm
// it works the following way:
// for an array of n integers, find the largest number,
// take it out of the array by deleting it, store it
// at the very end of the sorted array.
// Repeat until the original array is empty.
// If you need the original array, simply
// make a copy of it before sorting
/***************************************/
// second implementation
// same sorting algorithm
// main difference: the program automatically
// computes the number of numbers the user enters

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

int *sort(int *a, int n);                         // sort: the actual sorting function
char *read_line(char *str,int *num_of_chars);     // read_line: reads input in string form
int *create_array(char *str, int n);              // create_array: counts the num of integers entered and extracts them
                                                  // from the string the read_line function returns, forming an array
int size_of_array_to_be_sorted = 0;               // of integers

int main(void)
{
  int *array, i, *sorted_array, size = 3;
  char *str = malloc(size + 1);

  if (str == NULL)
  {
    printf("\nERROR: malloc failed for str.\nTerminating.\n");
    exit(EXIT_FAILURE);
  }
  printf("Enter the numbers to be sorted: ");
  str = read_line(str, &size);

  array = create_array(str, size + 1);
  sorted_array = sort(array, size_of_array_to_be_sorted);

  printf("Sorted: ");
  for (i = 0; i < size_of_array_to_be_sorted; i++)
    printf("%d ", sorted_array[i]);
  printf("\n\n");

  return 0;
}

int *sort(int *a, int n)
{
  int i, j, *p, *sorted_array, current_max;

  sorted_array = malloc(n * (sizeof(int)));
  if (sorted_array == NULL)
  {
    printf("ERROR: malloc failed in sort function.\nTerminating.\n");
    exit(EXIT_FAILURE);
  }

  for (i = n - 1; i >= 0; i--)      // repeat algorithm n times
  {
    current_max = a[0];             // intiliaze current_max with the first number in the array
    p = a;
    for (j = 0; j < n; j++)         // find the largest integer int the array
      if (current_max < a[j])
      {
        current_max = a[j];
        p = (a + j);                // make p point to the largest value found
      }
    *p = INT_MIN;                        // delete the largest value from the array
    sorted_array[i] = current_max;       // store the largest value at the end of the sorted_array
  }

  return sorted_array;
}

char *read_line(char *str, int *num_of_chars)
{
  int i = 0;     // num of chars initially
  char ch, *str1 = str;

  while ((ch = getchar()) != '\n')
  {
    str1[i++] = ch;
    if (i == *num_of_chars)                             // gives str the possibility to
    {                                                   // dinamically increase size if needed
       str1 = realloc(str, (*num_of_chars)++);
       if (str1 == NULL)
       {
         printf("\nERROR: realloc failed in read_line.\nTerminating.\n");
         exit(EXIT_FAILURE);
       }
     }
  }
  // at the end of the loop, str1 will contain the whole line
  // of input, except for the new-line char. '\n' will be stored in ch
  str1[i++] = ch;
  str1[i] = '\0';  // store the null char at the end of the string

  return str1;
}

int *create_array(char *str, int n)
{
  int *array, i, j, k, num_of_ints = 0;

  for (i = 0; i < n; i++)                         // computing number of numbers entered
    if (str[i] == ' ' || str[i] == '\n')
      num_of_ints++;

  array = calloc((size_t) num_of_ints, sizeof(int));    // allocacting necessary space for the array
  if (array == NULL)
  {
    printf("\nERROR: calloc failed in create_array.\nTerminating.\n");
    exit(EXIT_FAILURE);
  }

  k = 0;
  i = 1;                          // populating the array
  for (j = n - 1; j >= 0; j--)
  {
    switch (str[j])
    {
      case '0': case '1': case '2':
      case '3': case '4': case '5':
      case '6': case '7': case '8':
      case '9': array[k] += ((str[j] - '0') * i);
                i *= 10;
                break;
      case '-': array[k] = -array[k];     // added to support negative integers
      default:  i = 1;
                if (str[j] == ' ' && (str[j - 1] >= '0' && str[j - 1] <= '9'))
                     /* only increment k
                      *right before a new integer
                      */
                  k++;
                break;
    }                                                                      
  }
  // the loop works in this way:
  // it reads the str string from the end
  // if it finds a digit, it will try to extract it from the
  // string and store in array, by adding to one of the elements
  // of array the current char - ASCII for '0', so that it actually gets a digit,
  // times the position of that digit in the number,
  // constructing the number in base 10: units have 1, decimals 10, hundreds 100, and so on
  // when it finds a char that's not a digit, it must be a space, so it resets i
  // and increments k, to construct a new number in the next element of array

  size_of_array_to_be_sorted = num_of_ints;
  return array;
}

I've written everything myself, so if you think I use some bad methods or naive approaches or something, please tell me, in order for me to be able to correct them. Anyways, my problem is that I have these 'try to handle errors' if statements, after every call of malloc, calloc or realloc. I have a Linux machine and a Windows one. I wrote the program on the Linux one, which has 4GB of RAM. I wrote it, compiled with gcc, had to change a few things in order to make it work, and it runs flawlessly. I have no problem. I then copied it onto a USB drive and compiled it with mingw on my Windows machine, which has 8GB of RAM. I run it, and if I give it more than 3 2-digit integers, it displays ERROR: realloc failed in read_line. Terminating. At least I know that the 'error handling' if statements work, but why does this happen? It's the same code, the machine has twice as much RAM, with most of it free, and it runs with no problem on Linux. Does this mean that my code is not portable? Is it something I don't do right? Is the algorithm wrong? Is the program very, very inefficient? Sorry for the long question. Thanks if you wanna answer it.


Show source
| sorting   | C   | linux   | algorithm   | windows   2016-12-27 18:12 1 Answers

Answers ( 1 )

  1. 2016-12-27 19:12

    The line in question is:

    str1 = realloc(str, (*num_of_chars)++);
    

    where *num_of_chars is the current size of str. Because you are using post-increment, the value passed for the new allocation is the same as the current one, so you haven't made str any bigger, but go ahead and act as if you had.

◀ Go back