0

This c program is working fine in windows but showing segment fault in Linux.

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

void comb(long int *arr,long int n,long int r,long int stick)
{
    long int check=1,sum =0;
    int poscheck = 0,status = 0;
    long int *temp = malloc(r * sizeof(long int));
    long int *pos = malloc(r * sizeof(long int));
    long int *rept = malloc(r * sizeof(long int));
    memset(pos, 0, r*sizeof(long int));
    memset(rept, 0, r*sizeof(long int));

    while (check <= pow(n,r))
    {
        for (long int i = 0; i < r; i++) //for making the number of array
        {
            for(long int j = 0; j < r; j++) //For checking that no number is repeating.
            {
                if(i == j) continue; //for skip checking of the same element
                else if(pos[i] == pos[j])
                {
                    poscheck = 1;
                    break;
                }
            }
            if(poscheck == 1) break;
            temp[i] = arr[pos[i]];
            sum += temp[i];
        }
        if((sum == stick) && poscheck == 0)
        {
            for(long int i = 0 ; i< r ; i++)
            {
                printf("%ld ",temp[i]);
            }
            status = 1;
            printf("\n");
            break;
        }
        sum = 0,poscheck = 0;
        for (long int i = 0; i < r; i++)
        {
            if (pos[i] == n - 1)
            {
                rept[i]++; //To check how much time the number is repeated in a column
            }
            if ((pos[i] == n - 1) && (rept[i] == pow(n, r-i-1))) //If it is repeated a specific number of time then change the value of it's previous position
            {
                if (pos[i - 1] == n - 1) //if the previous number is the last number then it will start the series again 
                {
                    pos[i - 1] = 0;
                }
                else
                    pos[i - 1]++; //If the previous number is not the last number of series then go to the next number
                rept[i] = 0;
            }
        }
        if (pos[r - 1] < n - 1) //for go to the next number of series in the last line
        {
            pos[r - 1]++;
        }
        else
        {
            pos[r - 1] = 0; //if it is the last number of series then start form the first again
        }
        check++;
    }
    if(status == 0)
    {
        printf("-1\n");
    }
    free(pos); //Does not know why this is showing "double free or corruption (out)" in linux but working in windows.
    free(rept);
    free(temp);
} 
int main()
{
    long int n,data[3],j=0;
    scanf("%ld",&n);
    long int *arr = malloc(n*sizeof(long int));
    while(j < n)
    {
        for(long int i = 0; i< 3; i++)
        {
            scanf("%ld",&data[i]);
        }
        for(long int i = 0; i < data[1]; i++)
        {
            arr[i] = i+1;
        }
        comb(arr,data[1],data[2],data[0]);
        j++;
    }
    free (arr);
    return 0;
}

The given input is

12 8 3
10 3 3
9 10 2
9 10 2

This is showing in linux

1 3 8 
-1
munmap_chunk(): invalid pointer
Aborted (core dumped)

This is showing perfectly in windows

2 3 7
-1
5 4
1 8

I used gcc and tcc both compiler in windows and Linux but both are giving same error in Linux.

Can't understand why the problem is showing in Linux.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
SID
  • 49
  • 5
  • 2
    If it is Linux where the wheels are falling off the wagon, they probably are on other platforms too. Being Linux, run your program through valgrind. If you're breaching allocated arrays and/or actually double-freeing something, odds are it will tell you the error of your ways. – WhozCraig Nov 02 '18 at 16:17
  • In `main()`, `arr[i]` would be out of bounds if `i >= n` and `data[1] > n`. I guess the input is coming from a trusted source for a coding challenge so that the inputs are guaranteed to be valid by the rules of the challenge. – Ian Abbott Nov 02 '18 at 16:23
  • I think you have shown the output, but not the input. If so, please show the input. – Ian Abbott Nov 02 '18 at 16:35
  • ok .... I am adding input also ...thank you for help. – SID Nov 12 '18 at 16:14

2 Answers2

0

If the input is

1 3 8 
-1

in main

n = 1

arr = memory for 1 long int

in for(long int i = 0; i< 3; i++)

data array = 3 8 -1

in: for(long int i = 0; i < data[1]; i++)

arr[i] = some value    

But arr array will iterate 8 times and attempt to assign arr[i], even though arr has one element.

lostbard
  • 5,065
  • 1
  • 15
  • 17
  • I assumed `1 3 8`, `-1` was the output. I don't think OP has specified the input. – Ian Abbott Nov 02 '18 at 16:32
  • maybe - I was assuming it was a mix with the first 4 values being the input. – lostbard Nov 02 '18 at 16:35
  • Well maybe. I have asked OP for clarification. – Ian Abbott Nov 02 '18 at 16:36
  • And you may be right, because usually for these sort of code challenges, the first number read is a number of tests to be performed, here counted by the `j` loop in `main`. Which I guess means OP should be `malloc`ing and `free`ing `arr` inside the `j` loop with a size of `data[1] * sizeof(long int)`. – Ian Abbott Nov 02 '18 at 16:41
  • Thank you for your ans...but 1 3 8 , -1 are the outputs not the input. I have updated the inputs also I think it will help @lostbard . – SID Nov 12 '18 at 16:52
0

for the lines starting with:

if (pos[i - 1] == n - 1) 

`i' will be 0 at times (on the input of 10 3 3) and so at that point you are setting pos[-1] to values - ie: setting memory you shouldn't be to something which is then interfering with the free later on as malloc uses values before the pointer for free information.

To validate,, if I added a print before the if compare and run your example:

if(i==0) printf("bad I pos\n");

It prints out in a number places before having the error.

lostbard
  • 5,065
  • 1
  • 15
  • 17
  • I updated the code but it's showing ```malloc.c:2401: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed. Aborted (core dumped)``` – SID Nov 12 '18 at 17:32
  • updated portion if ((pos[i] == n - 1) && (rept[i] == pow(n, r - i - 1))) { if (check != pow(n, r)) { if (pos[i - 1] == n - 1) { pos[i - 1] = 0; } else pos[i - 1]++; } – SID Nov 12 '18 at 17:39
  • Using you code above, it is still accessing I-1 when I is 0. Put the print statement after the if ((pos[i] == n - 1) && (rept[i] == pow(n, r-i-1))) line and you will see it. Update your code to what you now have – lostbard Nov 12 '18 at 17:54
  • yup, It accessing when i = 0 but not accessing i-1 while i = 0 – SID Nov 12 '18 at 17:58
  • if the code you have at the top is the current, then it still is - please update – lostbard Nov 12 '18 at 18:02
  • I updated that portion with this if ((pos[i] == n - 1) && (rept[i] == pow(n, r - i - 1))) { if (check != pow(n, r)) { if (pos[i - 1] == n - 1) { pos[i - 1] = 0; } else pos[i - 1]++; } – SID Nov 12 '18 at 18:03
  • if (pos[i - 1] == n - 1) { pos[i - 1] = 0; } else pos[i - 1]++; } looks like I-1 still to me – lostbard Nov 12 '18 at 18:06
  • while i = 0 the pos[i-1] is accessed only when check = pow(n,r). now I made a specia check for the last element . that prevent accessing pos[i-1] when i = 0. – SID Nov 12 '18 at 18:09