Large array causing segmentation fault - c

I wrote a code with the following specified constraints:
Hence I chose the data types for my variables accordingly.
However my code fails all the test cases saying segmentation fault. (possibly because the array size they input is very large.) Is there a way to get more stack space or heap space? or get around this problem by declaring the array in some other way? Is there something else that's causing segmentation fault? Other people have solved this problem, so there must be a way.
this is the code:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
long find_index(long x, long *cost, long n, long used_index)
{
long i;
for(i = 0; i < n; i++)
if(*(cost + i) == x && i != used_index)
return (i+1);
return 0;
}
int purchase(long *cost, long n, long money)
{
long i, index;
for(i = 0; i < n ;i++)
{
index = find_index((money - *(cost - i)),cost,n,i);
if(index)
{
printf("%ld %ld\n",i+1,index);
break;
}
}
free(cost);
return 0;
}
int main(void)
{
int t;
long *cost, money, n, i;
scanf("%d",&t);
while(t > 0)
{
scanf("%ld",&money);
scanf("%ld",&n);
cost = (long *)malloc(n*sizeof(long));
for(i = 0; i < n; i++)
scanf("%ld",(cost+i));
purchase(cost,n,money);
t--;
}
return 0;
}
this is one of the hidden test cases they check for:
35 // this is t
299701136 // this is money
2044 // this is n
50293811 136626876 58515785 59281065 ..... goes on forever...

That's a lot of complex code to analyze, so instead of giving you a fish, I'll try to give you a rod.
Whatever platform, compiler and IDE you're using, there probably is a way to perform step-by-step debugging of your program at runtime. Maybe your assumptions are wrong and the allocation size is not causing this problem.
Learning basics of debugging is really great tool in programmer's hands. Here is an example tutorial video: https://www.youtube.com/watch?v=9gAjIQc4bPU

These changes in the code fix the issue of array index out of bounds problem, Hence the segmentation fault issue:
if((money - *(cost + i)) < n)
index = find_index((money - *(cost + i)),cost,n,i);
The constraints mentioned cause no issue.

Related

How to avoid SIGSEGV Error in Insertion Sort

I am trying to implement Insertion sort algorithm in C.
But all I get is SIGSEGV error in online IDEs and the output doesn't show up in Code::Blocks. How to avoid Such errors.
#include <stdio.h>
#include <stdlib.h>
int main()
{
/* Here i and j are for loop counters, temp for swapping
count for total number of elements,array for elements*/
int i, j, temp, count;
printf("How many numbers are you going to enter");
scanf("%d", &count);
int n[20];
printf("Enter %d elements", count);
// storing elements in the array
for(i = 0; i < count; i++) {
scanf("%d", n[i]);
}
// Implementation of insertion sort algorithm
for(i = 0; i < count; i++) {
temp = n[i];
j = i - 1;
while(temp < n[j]) {
n[j+1] = n[j];
j = j - 1;
}
n[j+1] = temp;
}
printf("Order of sorted elements");
for(i = 0; i < count; i++) {
printf("%d", n[i]);
}
return 0;
}
There are a couple of problems with your code. First of all, what is a SIGSEGV error? Well, it's another name for the good old Segmentation fault error, which is basically the error you get when accessing invalid memory (that is, memory you are not allowed to access).
tl;dr: change scanf("%d",n[i]); to scanf("%d",&n[i]);. You're trying to read the initial values with scanf("%d",n[i]);, this raises a segmentation fault error because scanf expects addresses in which put the values read, but what you're really doing is passing the value of n[i] as if it were an address (which it's not, because, as you did not set any value for it yet, it's pretty much just memory garbage). More on that here.
tl;dr: change int n[20]; to int n[count]. Your array declaration int n[20]; is going to store at most 20 integers, what happens if someone wants to insert 21 or more values? Your program reserved a certain stack (memory) space, if you exceed that space, then you're going to stumble upon another program's space and the police (kernel) will arrest you (segmentation fault). Hint: try inserting 21 and then 100 values and see what happens.
tl;dr: change for(i = 0; i < count; i++) { to for(i = 1; i <= count; i++) {. This one is a logic problem with your indexes, you are starting at i = 0 and going until i = count - 1 which would be correct in most array iteration cases, but as j assumes values of indexes before i, you need i to start from 1 (so j is 0, otherwise j = -1 in the first iteration (not a valid index)).
My final code is as follows. Hope it helped, happy coding!
#include <stdio.h>
#include <stdlib.h>
int main() {
/*Here i and j are for loop counters,temp for swapping
count for total number of elements,array for elements*/
int i, j, temp, count;
printf("How many numbers are you going to enter?\n");
scanf("%d",&count);
int n[count];
printf("Enter %d elements\n",count);
//storing elements in the array
for(i = 0; i < count; i++) {
scanf("%d", &n[i]);
}
//Implementation of insertion sort algorithm
for(i = 1; i <= count; i++) {
temp = n[i];
j = i-1;
while(temp < n[j]) {
n[j+1] = n[j];
j--;
}
n[j+1] = temp;
}
printf("Order of sorted elements\n");
for(i = 0; i < count; i++) {
printf("%d\n",n[i]);
}
return 0;
}
Edit: If you're having trouble with online IDEs, consider running your programs locally, it saves a lot of time, plus: you never know what kernel version or magic the online IDEs are using to run your code (trust me, when you're coding in C -- fairly low level language, these things make a difference sometimes). I like to go all root style using Vim as text editor and gcc for compiling as well as gdb for debugging.

Segmentation Fault in a C function

I hope you have spent beautiful Christmas holidays. I am studying for an exam and I have a problem with my project in ANSI C. My code works but not always, it's strange because for some input values it works for other not. I have two arrays, A and B, that must be different in size and I have to write a function that do the mathematical union of the two arrays in another array. If there are elements of the same value I have to insert in the new array only one. I write all the code (I also post a question here because I had some problems with the union) but it does not work always. Gcc compile and I execute but it's not correct. I debugged with gdb and it said
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400d1c in unionearraycrescente (a=0x7fffffffdd50, indice_m=4,
b=0x7fff00000005, indice_n=5, minimo=6, indiceMinimo=22)
at array.c:152
152 if(b[i]==c[j])
And this is the code near the problem
int arrayun(int a[], int index_m, int b[], int index_n, int minimum, int indexMinimum)
{
int i=0;
int j=0;
int found;
int lenc=0;
int c[lenc];
for(i=0;i<index_m;i++){
found = 0;
for(j=0; j<i && !found;j++)
if(a[i]==c[j])
found = 1;
if(!found)
c[lenc++] = a[i];
}
for(i=0;i<index_n;i++){
found=0;
for(j=0;j<i && !found;j++)
{
if(b[i]==c[j]) //debug gbd problem - segfault
found = 1;
}
if(!found)
c[lenc++] = b[i];
}
I am Italian so the comments are in my language, if you have any problems I will translate the comments. I want only to resolve this memory error. Thank you.
I follow some of your advices and in that part of code it works, I changed all the variables with index_m and I don't receive segfault but after the union I use the selection sort to sort in ascending order and it return me not the right values but in the first position negative values.
int arrayun (int a[], int index_m, int b[], int index_n, int minimum, int indexMinimum)
{
int i=0;
int j=0;
int found;
int lenc;
int c[index_m];
for(i=0;i<index_m;i++){
found = 0;
for(j=0; j<i && !found;j++)
if(a[i]==c[j])
found = 1; //setta trovato = 1
if(!found)
c[index_m++] = a[i];
}
for(i=0;i<index_n;i++){ //index_m or index_n?
found=0;
for(j=0;j<i && !found;j++)
{
if(b[i]==c[j]) //debug gbd problem - segfault - SOLVED but
found = 1;
}
if(!found)
c[index_m++] = b[i];
}
for (i=0; i<index_m-1;i++)
{
minimum=c[i];
indexMinimum=i;
for (j=i+1;j<index_m; j++)
{
if (c[j]<minimum)
{
minimum=c[j];
indiexMinimum=j;
}
}
c[indexMinimum]=c[i];
c[i]=minimum;
}
for(i=0;i<index_m;i++)
printf("Element %d\n",c[i]);
return c[index_m]; //I think here it's wrong
}
int c[lenc]; means in your program it is c[0]
and you are allocating ZERO Memory for the array.
And if you try for b[i]==c[i] where i>=0 means its a segmentation fault only.
Instead you can initialize like,
c[index_m];
int lenc=0;
int c[lenc];
this is array of 0 length.and in loop you are trying to access c[1],c[2]... etc.
To cure this problem you can pass length of the bigger array
int unionearraycrescente (int a[], int index_m, int b[], int index_n,int len, int minimum, int indexMinimum)
and you can then initialize like
int c[len];

Why do some C programs work in debug but not in release?

Ok,
So I am stuck here. I have code for a program that systematically executes people standing in a circle based off an algorithm, but I am having a problem with it crashing in release mode. My code runs fine if I run it using the debugger (codeblocks), but if I don't it crashes. I looked around online, and the only thing I am finding is unintialized variables, but I tried immediately setting values for my variables at declaration and it didn't fix the problem.
If anyone can see what my problem is, I would greatly appreciate help.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// if the program does not work, please run in debugger mode. It will work.
void remove_person(int** array, int arraySize, int position)
{
int i;
for (i = 0; i < arraySize; ++i)
printf("%d ", (*array)[i]);
printf("\n");
int* temp = malloc((arraySize - 1) * sizeof(int)); // create temporary array smaller by one element
memmove(temp,*array,(position+1)*sizeof(int)); // copy entire array before position
memmove(temp+position,(*array)+(position+1),(arraySize - position)*sizeof(int)); // copy entire array after postion
for (i = 0; i < arraySize - 1; ++i)
printf("%d ", (temp)[i]);
printf("\n");
free (*array);
*array = temp;
}
int kill(int** a, int n)
{
int pos = 0;
int round = 1;
while(n > 1)
{
pos = pos + 2 - (round % 2);
while(pos >= n)
pos = pos - n;
remove_person(a,n,pos);
n--;
while(pos >= n)
pos = pos - n;
round++;
}
return *a[0];
}
void main()
{
int n, survivor, i;
int* people;
printf("Enter number of people for Russian Roulette: \n");
scanf("%d", &n);
people = (int*) malloc(n*sizeof(int));
for(i=0; i < n; i++)
{
people[i] = i;
}
survivor = kill(&people, n);
printf("The survivor is person #%d\n", survivor);
}
The basic answer to the title question ("Why do some C programs work in debug but not in release?") is "when they invoke undefined behaviour".
Here, in
memmove(temp,*array,(position+1)*sizeof(int)); // copy entire array before position
memmove(temp+position,(*array)+(position+1),(arraySize - position)*sizeof(int)); // copy entire array after postion
you copy too much. To see why, observe that the first memmove copies to temp[0], temp[1], ..., temp[position], and the second copies to temp[position], temp[position+1], ..., temp[position+arraySize-position-1] = temp[arraySize-1] (note the overlap at temp[position]). But temp only has space for arraySize-1 elements -- you copied one more than it was allowed to hold, so you get undefined behaviour.
It probably works in debug but not release mode because the heap is laid out differently (debug-mode allocators may pad the allocations with extra space to catch bugs like this when running under a debugger or profiler).
The program segfaults if I enter 4 (or even numbers higher than 4) as input, but I won't go into the code to see why that happens.
Apart from that the program works just fine, the problem is that you don't see the output because I think you run it on windows.
That being said you should add something like scanf("%d", &n); at the end or run cmd.exe, go to the directory that holds the executable and run it from there.

Why is this C program crashing?

I have a simple test program in C to scramble an array of values on the heap. Sidenote: I know the random logic here has a flaw that will not allow the "displaced" value to exceed RAND_MAX, but that is not the point of this post.
The point is that when I run the code with N = 10000, every once in a while it will crash with very little information (screenshots posted below). I'm using MinGW compiler. I can't seem to reproduce the crash for lower or higher N values (1000 or 100000 for example).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N = 10000;
int main() {
int i, rand1, rand2, temp, *values;
/* allocate values on heap and initialize */
values = malloc(N * sizeof(int));
for (i = 0; i < N; i++) {
values[i] = i + 1;
}
/* scramble */
srand(time(NULL));
for (i = 0; i < N/10; i++) {
rand1 = (int)(N*((double)rand()/(double)RAND_MAX));
rand2 = (int)(N*((double)rand()/(double)RAND_MAX));
temp = values[rand1];
values[rand1] = values[rand2];
values[rand2] = temp;
}
int displaced = 0;
for (i = 0; i < N; i++) {
if (values[i] != (i+1)) {
displaced++;
}
}
printf("%d numbers out of order\n", displaced);
free(values);
return 0;
}
it may be because rand() generates a random number from 0 to RAND_MAX inclusive so (int)(N*((double)rand()/(double)RAND_MAX)) can be N, which exceeds the array boundary. however, i don't see why that would vary with array size (it does explain why it only crashes sometimes, though).
try /(1+(double)RAND_MAX) (note that addition is to the double, to avoid overflow, depending on the value of RAND_MAX) (although i'm not convinced that will always work, depending on the types involved. it would be safer to test for N and try again).
also, learn to use a tool from Is there a good Valgrind substitute for Windows? - they make this kind of thing easy to fix (they tell you exactly what went wrong when you run your program).

C program - weird Seg fault in dynamic programming algorithm

I'm writing a program in C to do a simple dynamic programming algorithm where you return the minimum number of coins needed to add up to a certain amount. Here's my code:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
/*
This function returns the minimum number of stamps required for a given value.
It assumes that the given array contains the available stamp sizes, and that it
always contains 1, so a solution is always possible
*/
int min_number_of_stamps(const int* array, size_t array_size, int request) {
/* Construct a table with dimensions (array_size+1)*(request+1) */
int numRows = array_size + 1;
int numCols = request + 1;
int **DPtable;
DPtable = malloc(numRows*sizeof(int));
int i;
for (i = 0; i < numRows; i++) {
DPtable[i] = malloc(numCols*sizeof(int));
}
printf("%d",DPtable[4][0]);
int r, c, useIt, loseIt;
for (r = 0; r < numRows; r++) {
for (c = 0; c < numCols; c++) {
printf("%d,%d\n", r, c);
if (c==0) {
printf("1\n");
//if the amount of change is 0, 0 coins are needed
DPtable[r][c] = 0;
}
else if ((r==0) || c < array[r-1]) {
printf("2\n");
//if there are no coins or if the change needed is less than
//the smallest coin available, then 'infinity' coins are needed
DPtable[r][c] = INT_MAX;
}
else {
printf("3\n");
useIt = DPtable[r][c-array[r-1]] + 1;
loseIt = DPtable[r-1][c];
if (useIt <= loseIt) {
//if 'use it' requires fewer coins than 'lose it,' then
//'use it' coins are needed.
DPtable[r][c] = useIt;
}
else {
//if 'lose it' requires fewer coins, 'lose it' coins are needed
DPtable[r][c] = loseIt;
}
}
}
}
return DPtable[numRows][numCols];
}
int main() {
const int array[] = {1,5,10,25};
const int* stamps = &array[0];
printf("%d", min_number_of_stamps(stamps, 4, 44));
}
I'm getting a segfault when my inner for loop gets to the case where r=4 and c=0. I left my debugging print statements in because I'm lazy, but you can see where I got stuck. If I access the same place in the array outside of my for loops, there's no problem. But in the for loop, I get a `Segmentation fault: 11' message after it outputs "4,0" for the array element and "1" for the if case it's in. Can anyone see what I'm missing?
Learn to enable warnings & debugging for your compiler, i.e. gcc -g -Wall on Linux.
Learn to use a debugger, i.e. gdb -tui on Linux.
Consider using valgrind
EDIT
Many tutorials (in several languages, e.g. English, French, ....) for GCC, GDB, and ValGrind are easily found on the Web.
You're allocating dpTable incorrectly. It should be
DPtable = malloc(numRows*sizeof(int*));
See if that fixes the problem.
return DPtable[numRows][numCols];
thats out of bounds isn't it?

Resources