The code is an implementation of the Gift Wrapping Algorithm. The input file is of the form 'X Y Z' on each line, and I don't need to consider the Z co-ordinate. The code works fine for smaller N like 100000 but gives segmentation fault for larger N value. Can some one explain me the reason for it?
#include <stdio.h>
#include <stdlib.h>
#define N 200000
struct Point{
double x,y;
};struct Point p[N];
int ori(struct Point p1, struct Point p2, struct Point p3);
int main(){
FILE *fp,*fp2;
fp2=fopen("out.txt","w");
int i=0;
fp=fopen("sample.txt","r");
if(fp==NULL){
printf("File not found!\n");
exit(0);
}
double g;
for(i=0;i<N;i++)
fscanf(fp,"%lf %lf %lf",&p[i].x,&p[i].y,&g);
int l=0;
for(i=1;i<N;i++){
if(p[i].x<p[l].x){
l=i;
}
}
int base=l,q;
int chullin[N];
for(i=0;i<N;i++)
chullin[i]=-1;
while(true){
q=(base+1)%N;
for(i=0;i<N;i++)
if(ori(p[base],p[i],p[q])==1)
q=i;
chullin[base]=q;
base=q;
if(base==l)
break;
}
int cnt=0;
int a[26];
for(i=0;i<N;i++)
if(chullin[i]!=-1){
a[i]=i;
fprintf(fp2,"%f %f %d\n",p[i].x,p[i].y,i);
cnt++;
}
return 0;
}
int ori(struct Point p1, struct Point p2, struct Point p3){
int val=p1.x*(p2.y-p3.y)-p1.y*(p2.x-p3.x)+(p2.x*p3.y-p3.x*p2.y);
if(val==0)
return 0;
if(val>0)
return 1;
else return -1;
}
you are totally overflowing the int array 'a' or at least accessing non-existent values within the array, which is on the stack... if chullin[i] != -1 for more than 26 points... or if chullin[i] where i>25, you are writing randoms on the stack.
int a[26];
for(i=0;i<N;i++)
if(chullin[i]!=-1){
a[i]=i; //problem here.
fprintf(fp2,"%f %f %d\n",p[i].x,p[i].y,i);
cnt++;
}
The problem is not in the array p, but in the array chullin. Try to dynamically allocate the array, using the malloc function:
int *chullin = (int*)malloc(sizeof(int)*N);
// do whatever you want with chullin
free(chullin);
Edit: I will try to explain the cause of the Segmentation fault. When you create a non-dynamic array inside a function, it is allocated in the heap. The heap has limited size, so when you declare a large array, the heap overflows. When you use malloc, you dynamically allocate the array, which means that it is allocated in the stack. The stack has much bigger size than the heap, so you are able to create larger arrays. Global arrays are also allocated in the stack, that's why you needn't allocate them dynamically...
Edit[2]: Array a has size 26, which means that when N is larger than or equal to 26 you will be accessing invalid memory locations, causing segmentation fault.
Related
when trying to print the values of struct variables after the function returns it prints some random text (which I think is due to memory allocation error)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char s1[20];
char s2[20];
int n1;
} TEST;
void allocate(TEST *T, int n){
T = malloc(sizeof(TEST)*n);
for(int i=0; i<n; i++){
sprintf((T+i)->s1, "string 1 of %d", i);
sprintf((T+i)->s2, "string 2 of %d", i);
(T+i)->n1 = i;
}
}
int main(){
TEST *T;
int n = 3;
allocate(T, n);
for(int i=0; i<n; i++){
printf("%s\n%s\n%d\n\n", (T+i)->s1, (T+i)->s2, (T+i)->n1);
}
}
No, C absolutely does not call free automatically for you.
The issue in your program is that T in the caller to allocate is not changed. C is strictly a pass by value language.
One solution is to change the type of T to TEST** in allocate:
void allocate(TEST **T, int n){
with
allocate(&T, n);
in main. You then call free in main.
The program causes undefined behaviour by passing uninitialized T to the function. Furthermore you never return the new pointer value from the function back to main.
The pointer to new memory is an output of the function, not an input. So it should be a return value, not a parameter. For example:
TEST* allocate(int n)
{
TEST* T = malloc(sizeof(TEST)*n);
// etc.
return T;
}
and then in main:
TEST* T = allocate(n);
// ... use T ...
free(T);
As said by the already given answers you need to call free to free the memory.
You want to allocate the pointed memory area, so you need a TEST**:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char s1[20];
char s2[20];
int n1;
} TEST;
void allocate(TEST **T, int n){
*T = malloc(sizeof(TEST)*n);
for(int i=0; i<n; i++){
sprintf((*T+i)->s1, "string 1 of %d", i);
sprintf((*T+i)->s2, "string 2 of %d", i);
(*T+i)->n1 = i;
}
}
int main(){
TEST *T;
int n = 3;
allocate(&T, n);
for(int i=0; i<n; i++){
printf("%s\n%s\n%d\n\n", (T+i)->s1, (T+i)->s2, (T+i)->n1);
}
free(T);
}
No. The problem with your program is that T is passed by copy to allocate, and the address to the allocated memory is assigned to this copy. To fix, you could make the first allocate parameter **T, pass in the address of T in main, and dereference the pointer to pointer in allocate and assign to it.
No, it doesn't. You need to free() malloc()ated memory yourself.
Your program, as is, leaks memory... but for this particular program it doesn't matter an awful lot since that memory is freed when the process dies.
I've been getting segmentation fault in this piece of code, in the part where I scanf for the values of the board. In the beginning, I scan two times for the dimensions.
#include <stdio.h>
#include <stdlib.h>
#include "maxsum.h"
int main() {
int x,y,n,m,**board;
scanf("%d %d",&n,&m);
board=malloc(n*sizeof(int));
if (board==NULL) {
printf("Unable to allocate memory \n");
return 1;
}
for (x=0;x<n;x++) {
*(board+x)=malloc(m*sizeof(int));
if (*(board+x)==NULL) {
printf("Unable to allocate memory \n");
return 1;
}
}
for (x=0;x<n;x++) {
for (y=0;y<m;y++) {
scanf("%d",&board[x][y]); // the error happens in this line ,and only when variable x is about to become n-1 when n>4 (very confused as to why)//
}
}
printf("%d \n",Solve(n,m,board)); //not relevant //
return 0;
}
You're not allocating the right amount of memory:
board=malloc(n*sizeof(int));
You're setting up board as an array of int *, but you're only allocating space for an array of int. Most likely an int is smaller than an int * on your system, so you're not allocating enough. You subsequently write past the end of allocated memory resulting in undefined behavior.
Change this allocation to:
board=malloc(n*sizeof(int *));
Or better yet:
board=malloc(n*sizeof(*board));
I've been trying to wrap my head around pointers in C now for a while but I seem to be stuck on a problem that has to do with memory. I'm working on a function that returns an array from another function multiple times and then should deallocate the array in the end. Returning the array once works just fine but if I try to return it more then once the program is aborted and I get a segmentation error. The code of this function is
double func(int n, int max, int s){
int i;
int *p;
int *q;
double diff_t;
//start timer
time_t start_t, end_t;
time(&start_t);
//generate the arrays and search for s
for(i=0;i<100;++i){
p=initarray(n,max);
q=sort(n,p);
search(s,n,q);
}
//calculate elapsed time
time(&end_t);
diff_t=difftime(end_t,start_t);
//deallocate array
free(p);
return(diff_t);
}
and the other functions used within this function are
int *initarray(int n, int max){
//allocate memory for the array
int *arr=malloc(n);
//initialize an array
....
//return the array
return(arr);
}
int *sort(int n, int *arr){
//sort the array
...
//return the array
return(arr);
}
int search(int i, int n, int *arr){
int j;
int index;
//search the array for i
...
//return the index of i in the array
return(index);
}
I then call func in the main function as
func(2000,10000,10)
Also whenever I try to deallocate the array with free(p), for example, the program is aborted and returns a double free or corruption error. So I basically have two problems: I can't get my function to return the array more than once and I'm not able to deallocate the array in the end. I've searched the internet high and low but could get nothing to work, so any help would be greatly appreciated!
I think the problem is simple. You are allocating memory multiple times. but you are freeing the memory only once. ie: the last memory block allocated. Just move the free(p) statement inside your for loop.
for(i=0;i<100;++i)
{
p=initarray(n,max);
q=sort(n,p);
search(s,n,q);
//deallocate array
free(p);
}
As I ask how can I read values from the memory which was put into a memory block by malloc/realloc?
I have a program which creates 2 memory blocks at first and extends until reach 32.Its working fine but in order not to lose values after realloc I start my scanf session with an integer called koru.Koru starts with 0 at the beginning and in every realloc I make its number half of the total amount of memory so I expect not to lose the values entered before realloc sessions but now I need to read what I wrote the memory so I will be sure that I didnt overwrite how can I do that ?
#include "stdio.h"
#include "stdlib.h"
int main()
{
int size=2;
int* p1;
int* p2;
int n;
p1=(int *)malloc((size*sizeof(int)));
int b=0;
int i=0;
int koru=0;
while(size<32)
{
if(i<size){
for(i=koru;i<size;i++)
{
printf("\nEnter value:");
scanf("%d",p1);
}
}
else if(boyut=i)
{
size=size*2;
p2 = (int*) realloc (p1,size*sizeof(int));
p1=p2;
koru=size/2;
printf("\nNOt enough size we make it %d also we protect %d that amount of memory"size,koru);
}
}
return 0;
}
I thought putting a array[i]=p1; and reading it after while loop will solve the problem but later I figured out that its cheating I am not reading from the memory block just reading from another array so this wont work too can somebody lead the way for me please ?
What my program does:
2 blocks memory malloc
takes values and fills it
When it fills improves the memory size multiplying by 2 realloc
starts reading from half number so it dont rewite
continues this progress until it reaches 32
Edit:Simplified question:
I put lots of values in the memory after while loop how can I read them ?
I tried to read it like this but all I get is 0
int counter =0;
while (counter<koru)
{
printf("\n%d",p1[counter]);
counter++;
}
return 0;
}
The correct code which creates a memory block with malloc and extends it with realloc after 32 it exits while loop and writes everything from the p1 pointer(from memory) thanks for help.
Working Code below:
#include "stdio.h"
#include "stdlib.h"
int main()
{
int boyut=2;
int* p1;
int* p2;
int n;
p1=(int *)malloc((boyut*sizeof(int)));
int b=0;
int i=0;
int koru=0;
while(boyut<16)
{
if(i<boyut){
for(i=koru;i<boyut;i++){
printf("\nDeğer Girin:");
scanf("%d", &p1[i]);
}
}
else if(boyut=i)
{
boyut=boyut*2;
p2 = (int*) realloc (p1,boyut*sizeof(int));
p1=p2;
koru=boyut/2;
printf("\nBoyut yetersiz yeni boyutu %d yapıyoruz önceki %d kadar alanı korumaya aldık",boyut,koru);
}
}
int counter =0;
while (counter<koru)
{
printf("\n%d",p1[counter]);
counter++;
}
return 0;
}
I'm not sure exactly what you are asking here, but to access the values in the memory, just use p1 as an array. p1[3] would give you the 4th integer in the memory block.
Just be sure to respect the array bounds.
Bonus problem: you're not even filling the array, you're overwriting the first element each time you input.
The simple solution is to remove p2 entirely and treat p1 as an array:
...
scanf("%d", &p1[i]);
...
Then to read:
int n;
for (n=0; n<i; n++)
printf("%d ", p1[n]);
However, if you want to do it with two pointers instead of array indexing, you need one pointer to track the whole array for malloc and realloc, and the other to track where the current value is for reading/writing.
Initially the array is empty, so they are the same:
p1 = (int *)malloc(boyut * sizeof(int));
p2 = p1;
...
Input only uses the read/write pointer, and increments it each time:
...
scanf("%d", p2++);
...
Memory management only uses the "base" pointer
...
p1 = (int *)realloc(p1, boyut * sizeof(int));
...
(note you should strictly use a temporary variable for the return value of realloc() to check for failure, otherwise you could lose the value of p1)
Then to read we reset the read/write pointer to the start, and iterate through:
int n;
p2 = p1;
for (n=0; n<i; n++)
printf("%d ", *p2++);
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int queensonboard(int n,int m)
{
int count=0,i,j,flag,x[100];
char **board;
/* board= (char**)calloc(sizeof(char*),n);
for(i=0;i<n;i++)
{
board[i]= (char*)calloc(sizeof(char),m);
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&board[i][j]);
}
}*/
// x==(int*)calloc(sizeof(int),n);
flag=0;
for(i=0;i<n;i++)
{
x[i]=0;
}
while(i>0)
{
while(x[i]<m)
{
x[i]++;
// if(board[i][x[i]]!='#')
// {
for(j=0;j<i;j++)
{
if(x[j]==x[i])
{
flag=1;
}
else if(x[j]-x[i]==abs(j-i))
{
flag=1;
}
else
{
flag=0;
}
}
if(flag==0 && i==n-1)
{
count++;
}
else if(flag==0)
{
i++;
}
//}
}
x[i]=-1;
i--;
}
printf("%d\n",count);
}
int main() {
int i,n,m,j;
scanf("%d",&i);
for(j=1;j<=i;j++)
{
scanf("%d %d",&n,&m);
queensonboard(n,m);
}
return 0;
}
This is the code. The program gives segmentation fault on dynamically allocating any of the arrays x or board.(Commented here.)
That is when i try to allocate with calloc.
Couldnt really figure out why this is happening. Tried changing thins and that but still happening.
The definition of calloc is as follows:
void *calloc(size_t num, size_t size);
num Number of elements to allocate.
size Size of each element.
You have your arguments swapped. It should be like this:
board = calloc(n, sizeof(char *));
for(i = 0; i < n; i++)
{
board[i]= calloc(m, sizeof(char));
}
Also, this line is incorrect:
x == (int*)calloc(sizeof(int), n);
This, is comparing the address of x to the address that calloc returns. The logic is incorrect too. The way you have x defined, it is an array of 100 ints.
If you want an array of int pointers, you need to do this:
int *x[100];
If you want a pointer to array of 100 ints, you need to do this:
int (*x)[100];
If you're simply trying to allocate memory for x, you've already accomplished that with your declaration:
int x[100];
The obvious explanation for a segmentation fault is that you are de-referencing an invalid pointer. The obvious way for that to happen would be for any of the calls to calloc to return NULL. And calloc does that when it fails. You are not checking the return value of calloc for errors and I think it very likely that one of the calls returns NULL because you supplied invalid parameters.
So, debug the problem by checking the return value of the calls to calloc, and checking the input parameters that you pass. I know it's frustrating to have to do this, but you must check for errors in all user input, and you must check the return values of all calls to memory allocation functions.
This line
x==(int*)calloc(sizeof(int),n)
where you perform comparison rather than assignment is also clearly problematic. You meant:
int *x = calloc(n, sizeof(int));
And yes, you have the arguments to calloc swapped as others point out. You should certainly fix that but I do not believe that to be the cause of your problem.