#include <stdio.h>
#include <stdlib.h>
#include "frac_heap.h"
#define ARRAYSIZE 10
#define ENDOFARRAY 999
fraction heap[ARRAYSIZE] = {0};
block freeBlocks[ARRAYSIZE] = {0};
int startingBlock = 0;
int nextFree = 0;
fraction* fracPointers[][ARRAYSIZE] = {0};
block* blockPointers[][ARRAYSIZE] = {0};
void init_Heap(){
int x;
for(x = 0; x < ARRAYSIZE; x ++){
block *currBlock = &freeBlocks[x];
currBlock->isFree = 1;
fraction *fractionPointer = &heap[x];
if(x<ARRAYSIZE - 1){
fractionPointer->denominator = x+1;
}
else if(x == ARRAYSIZE - 1){
fractionPointer->denominator = ENDOFARRAY;
}
}
}
void dump_heap(){
int x;
for(x = 0; x < ARRAYSIZE; x ++){
fraction* tempFrac = &heap[x];
printf("%d\t%d\t%d\n",tempFrac->sign, tempFrac->numerator, tempFrac->denominator);
}
}
fraction* new_frac(){
fraction* testFraction = &heap[0];
if(testFraction->numerator == 0 && testFraction ->denominator==0){
printf("Before return");
return testFraction;
}
}
int main(){
init_Heap();
dump_heap();
fraction *p1;
p1 = new_frac();
p1->sign = -1;
p1->numerator = 2;
p1->denominator = 3;
dump_heap();
}
I get segmentation faults when trying to call new_frac(). At this point im just testing the code and I realize that testfraction wont always be = &heap[0];. However, I thought I was able to access parts of the struct that I am point to with '->'?
After editing it some more, it seems to only segfault when it reaches testFraction->denominator. If I only check for the denominator it still segfaults, but it works fine with just the numerator.
The issue is that not all code paths through new_frac() actually return a value. You then proceed to assign through this potentially uninitialized pointer:
p1 = new_frac();
p1->sign = -1;
p1->numerator = 2;
p1->denominator = 3;
Related
I'm trying to learn how to multithread with c, and thought that the longest palindromic subsequence problem would be a good place to start.
The idea is that we run two threads and compare their results to find the answer. One thread deals with "odd" subsequences, the other with "even" ones.
Although the code below seems to work, my question is: where in the program should I check for multi-threading errors? It is very new to me so I just need to know what parts may be prone to the issues that multi-threading brings.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct str{
char* seq;
int len;
};
void *odd(void* arg){
struct str index = *(struct str*)arg;
int maxAns = 1;
for(int i = 1; i < index.len; i++){
int low = i - 1;
int high = i + 1;
int currMax = 1;
while(low >= 0 && high < index.len && index.seq[low] == index.seq[high]){
low--;
high++;
currMax=currMax+2;
}
if(currMax > maxAns){
maxAns = currMax;
}
}
int* res = malloc(sizeof(int));
*res = maxAns;
free(arg);
return (void*)res;
}
void *even(void* arg){
struct str index = *(struct str*)arg;
int maxAns = 0;
for(int i = 0; i < index.len; i++){
int low = i;
int high = i + 1;
int currMax = 0;
while(low >= 0 && high < index.len && index.seq[low] == index.seq[high]){
low--;
high++;
currMax=currMax+2;
}
if(currMax > maxAns){
maxAns = currMax;
}
}
int* res = malloc(sizeof(int));
*res = maxAns;
free(arg);
return (void*)res;
}
int main(void){
char seq0[] = "aaasaaasadaadsdafa";
int len = sizeof(seq0)/sizeof(seq0[0])-1;
struct str* s0 = malloc(sizeof(struct str));
struct str* s1 = malloc(sizeof(struct str));
s0->seq = (char*)seq0;
s1->seq = (char*)seq0;
s0->len = len;
s1->len = len;
pthread_t t0;
pthread_t t1;
int* res0;
int* res1;
if (pthread_create(&t0, NULL, &odd, s0)!=0){
return 0;
}
if (pthread_create(&t1, NULL, &even, s1)!=0){
return 00;
}
if(pthread_join(t0, (void**)&res0)!=0){
return 1;
}
if(pthread_join(t1, (void**)&res1)!=0){
return 11;
}
if(*res0 > *res1){
printf("%d\n", *res0);
}else{
printf("%d\n", *res1);
}
free(s0);
free(s1);
return 0;
}
I'm doing a homework for learning graphs. For that, I'm taking a csv file and I keep that information in a Sensor structure.
#define sensor_amount 70
typedef struct Sensor {
int id;
float x,y,z;
}Sensor;
For getting this struct from file I'm using the following function:
Sensor* get_sensors(char* file_name){
FILE* file = fopen(file_name,"r");
//Skip first line
char* c;
fscanf(file,"%[^\n]",c);
int id = 0;
float x,y,z;
Sensor* sensor_arr = malloc(sizeof(Sensor));
fscanf(file,"%i,%f,%f,%f",&id,&x,&y,&z);
sensor_arr[0].id = id;
sensor_arr[0].x = x;
sensor_arr[0].y = y;
sensor_arr[0].z = z;
int counter = 1;
while(!feof(file)){
fscanf(file,"%i,%f,%f,%f\n",&id,&x,&y,&z);
++counter;
sensor_arr = realloc(sensor_arr,counter*sizeof(Sensor));
sensor_arr[counter-1].id = id;
sensor_arr[counter-1].x = x;
sensor_arr[counter-1].y = y;
sensor_arr[counter-1].z = z;
}
fclose(file);
return sensor_arr;
}
I'm calculating distances between each sensor with following code:
float** get_distances(Sensor* s){
float** a = malloc(sensor_amount*sizeof(float*));
for(int i = 0; i < sensor_amount;i++)
a[i] = malloc(sensor_amount*sizeof(float));
for(int i = 0; i < sensor_amount;i++){
for(int j = 0; j < sensor_amount; j++){
float dis = distance(s[i].x,s[i].y,s[j].x,s[j].y);
a[i][j] = dis;
}
}
return a;
}
Finally in my main i print those values like this:
int i,j;
int main(){
char file_name[] = "sensor_locations.csv";
Sensor* sensors;
sensors = get_sensors(file_name);
float**ar=get_distances(sensors);
for(i=0;i < 70; ++i)
for(j=0;j<70;++j){
printf("(%i,%i)->%f\n",i,j,ar[i][j]);
}
return 0;
}
In main, if I move the declarations of i and j to the for loops, it throws a segmentation fault. But why?
This is designed for array out of bounds bugs:
int counter = 1;
...
++counter;
...
[counter-1]
Instead do
for(int i=0; more_data; i++)
{
sensor_arr[i] = ...;
sensor_arr = realloc(sensor_arr,(i+2)*sizeof(Sensor));
}
Please note Why is “while ( !feof (file) )” always wrong?.
And your use of realloc is wrong, use a tmp pointer for storing the result and check it against NULL before assigning it back to the sensor_arr pointer.
I have a 3D matrix mat[100][100][100]. What is the efficient way to find a row with same elements that appears in mat[0][][], mat[1][][],....,mat[99][][]?
A simple approach would be comparing each row of mat[0][][] to all rows of the remaining 99 matrices, but it wouldn't be very efficient(I guess). Is there a better way to do it?
To expand on the comment by #chux, the first step is to compute a hash value for each row of each matrix. That's 10000 hash values in all. The results should be stored in an array of 10000 structs.
struct info
{
int m; // the matrix number
int row; // the row number
uint32_t hash; // the hash value for mat[m][row]
};
static struct info hashArray[10000];
After filling in all 10000 entries of the hashArray, sort the array by hash value. Then you can simply scan the array to find any duplicate hash values. When you do find duplicates, you need to confirm by comparing the row elements.
I finally found some time to write the content addressable code. It turns out to be much faster than using hash tables. But the catch is that the code is way more complex and the program takes WAY more memory. My final opinion is that unless you really need the extra speed, stick with the hash table.
Some examples of test runs are given below. The argument to the program specify the number of unique rows. The program fills the rest with randomly chosen existing rows. Then the rows are shuffled. The program looks for all duplicate rows and reports the number of duplicate rows and the time it took for both hash and content addressable tables.
bing#mint5 ~ $ cc -O2 cattest.c -o cattest
bing#mint5 ~ $ ./cattest 500
CAT Test 9500 0.0083
Hash Test 9500 0.0499
bing#mint5 ~ $ ./cattest 5000
CAT Test 5000 0.0195
Hash Test 5000 0.1477
bing#mint5 ~ $ ./cattest 9000
CAT Test 1000 0.0321
Hash Test 1000 0.1092
/* content addressable table vs hash table */
/* written by Bing H Bang */
/* I DONOT give permission to any snot-nosed students to copy my work and turn it in
as their own */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/sysinfo.h>
double etime()
{
struct timeval tv;
double dt, df;
gettimeofday(&tv, NULL);
dt = (double)(tv.tv_sec);
df = ((double)(tv.tv_usec))/1000000.0;
return(dt+df);
}
struct CAT_entry
{
unsigned fval;
unsigned short rows[10000];
unsigned short num;
unsigned short used;
struct CAT_entry *next;
} *CAT[256] = {NULL};
struct CAT_entry stmem[10000];
int stidx = 0;
unsigned dat[100][10000];
char map[10000];
unsigned hasht[10000];
#define highbit (1 << ((sizeof(unsigned)*8)-1))
unsigned
rotxor(unsigned sum, unsigned v)
{
if((sum & highbit) == 0)
return ((sum << 1) ^ v);
else
return (((sum << 1) | 1) ^ v);
}
unsigned
compute_hash(int y)
{
int x;
unsigned sum = 0;
for(x = 0; x < 100; ++x)
sum = rotxor(sum, dat[x][y]);
return sum;
}
void
mk_hasht()
{
int y;
for(y = 0; y < 10000; ++y)
hasht[y] = compute_hash(y);
}
clearmap()
{
memset((void *)map, 0, 10000);
}
comprow(int y, int yd)
{
int x;
for(x = 0; x < 100; ++x)
if(dat[x][y] != dat[x][yd])
return 0;
return 1;
}
struct CAT_entry **
srch_CAT(unsigned value)
{
struct CAT_entry **p = &(CAT[value&255]);
static struct CAT_entry *r = NULL;
while(*p != NULL)
{
if((*p)->fval == value)
break;
if((*p)->fval > value)
return &r;
else
p = &((*p)->next);
}
return p;
}
void
add_entry(int y, unsigned value)
{
struct CAT_entry **p = &(CAT[value&255]), *q;
while(*p != NULL)
{
q = *p;
if(q->fval == value)
{
q->rows[q->num] = y;
q->num++;
return;
}
if(q->fval > value)
break;
p = &(q->next);
}
q = *p;
//*p = malloc(sizeof(struct CAT_entry));
*p = &stmem[stidx++];
(*p)->next = q;
q = *p;
q->fval = value;
q->num = 0;
q->used = 0;
}
void
mk_CAT()
{
int x,y;
struct CAT_entry **p, *q;
for(y = 0; y < 10000; y++)
add_entry(y, dat[0][y]);
for(x=0; x < 256; ++x)
{
p = &(CAT[x]);
while(*p != NULL)
{
q = *p;
if(q->num == 0)
{
*p = q->next;
//free(q);
}
else
p = &(q->next);
}
}
}
void
gen_data(int npat)
{
int x, y, rnum, limit;
unsigned r;
srandom(time(NULL));
rnum = npat * 100;
for(y = 0; y < rnum; ++y)
dat[y%100][y/100] = random();
for(y = npat; y < 10000; ++y)
{
rnum = random() % npat;
for(x = 0; x < 100; ++x)
dat[x][y]=dat[x][rnum];
}
for(y = 0; y < 10000; ++y)
{
rnum = random() % 10000;
if(rnum == y)
continue;
for(x = 0; x < 100; ++x)
{
r = dat[x][y];
dat[x][y]=dat[x][rnum];
dat[x][rnum] = r;
}
}
}
int
do_CATtest()
{
int y, yd, count = 0, i;
struct CAT_entry **p, *q;
mk_CAT();
clearmap();
for(y = 0; y < 9999; ++y)
{
if(map[y] == 0)
{
map[y] = 1;
if(*(p = srch_CAT(dat[0][y])) != NULL)
{
for(q = *p, i = 0; i < q->num; ++i)
{
yd = q->rows[i];
if(map[yd] == 0)
{
if(comprow(y, yd))
{
map[yd] = 1;
++count;
q->used++;
}
}
}
if(q->num <= q->used)
*p = q->next;
}
}
}
return count;
}
int
do_hashtest()
{
unsigned h;
int x, y, yd, count = 0;
mk_hasht();
clearmap();
for(y = 0; y < 9999; ++y)
{
if(map[y] != 0)
continue;
map[y] = 1;
h = hasht[y];
for(yd = y+1; yd < 10000; ++yd)
{
if(map[yd] != 0)
continue;
if(h == hasht[yd])
if(comprow(y, yd))
{
map[yd] = 1;
++count;
}
}
}
return count;
}
main(int c, char *v[])
{
int npat = 0, count;
double t1, t2;
if(c == 2)
npat = atoi(v[1]);
if(npat <= 0 || npat >= 10000)
{
puts("input param error");
exit(1);
}
gen_data(npat);
npat = 10000 - npat;
t1 = etime();
if((count = do_CATtest()) != npat)
{
printf("CAT test error, %d matches found, not %d", count, npat);
exit(1);
}
t2 = etime();
printf("CAT Test %d %.4f\n", npat, t2-t1);
t1 = etime();
if((count = do_hashtest()) != npat)
{
printf("hash test error, %d matches found, not %d", count, npat);
exit(1);
}
t2 = etime();
printf("Hash Test %d %.4f\n", npat, t2-t1);
}
Make a content addressable table of the first values in each row. Then go through each row, take the first value and look it up on the table. If the lookup returns multiple rows, then those rows should be checked for a match. The searched rows should be remembered as to increase efficiency because the checked rows need not be checked again. You'll end up with a list of identical row groupings.
I am trying get a mandelbrot image clearly with the sequential programming in C++, but I am getting a segmentation fault during runtime. I have no idea about the seg. fault, but my program is perfectly compiling with no errors.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int file_write(unsigned int width, unsigned int height)
{
unsigned int **color = NULL;
FILE *fractal = fopen("mandelbrot_imageSequential.ppm","w+");
if(fractal != NULL)
{
fprintf(fractal,"P6\n");
fprintf(fractal,"# %s\n", "Mandelbrot_imageSequential.ppm");
fprintf(fractal,"%d %d\n", height, width);
fprintf(fractal,"40\n");
int x = 0, y = 0;
unsigned int R = 0, G = 0, B = 0;
for(x = 0; x < width; ++x)
{
for(y = 0; y < height; ++y)
{
R = (color[y][x]*10);
G = 255-((color[y][x]*10));
B = ((color[y][x]*10)-150);
if(R == 10)
R = 11;
if(G == 10)
G = 11;
if(B == 10)
B = 11;
putc(R, fractal);
putc(G, fractal);
putc(B, fractal);
}
}
fclose(fractal);
}
return 0;
}
int method(int x, int y, int height, int width, double min_re, double max_re, double min_im, double max_im, int max_iterations)
{
double threshold = 4;
double x_factor = (max_re-min_re)/(width-1);
double y_factor = (max_im-min_im)/(height-1);
double c_im = max_im - y*y_factor;
double c_re = min_re + x*x_factor;
double Z_re = c_re, Z_im = c_im;
unsigned int col = 0;
for(unsigned n = 0; n < max_iterations; ++n)
{
double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im;
if(Z_re2 + Z_im2 > threshold)
{
col = n;
break;
}
Z_im = 2 * Z_re * Z_im + c_im;
Z_re = Z_re2 - Z_im2 + c_re;
}
return col;
}
int main(int argc, char *argv[])
{
unsigned int width;
unsigned int height;
unsigned int max_iterations;
unsigned int **color = NULL;
int x,y;
double threshold;
double min_re;
double max_re;
double min_im;
double max_im;
unsigned int NUM_OF_THREADS;
if(argc != 10)
{
printf("There is an error in the input given.\n");
return 0;
}
else
{
height = atoi(argv[1]);
width = atoi(argv[2]);
max_iterations = atoi(argv[3]);
min_re = atof(argv[4]);
max_re = atof(argv[5]);
min_im = atof(argv[6]);
max_im = atof(argv[7]);
threshold = atoi(argv[8]);
NUM_OF_THREADS = atoi(argv[9]);
}
color = (unsigned int**)malloc(height*sizeof(unsigned int*));
printf("height = %d\twidth = %d\tmaximum_iterations = %d\tminimum_x-value = %.2f\tmaximum_x-value = %.2f\tminimum_y-value = %.2f\tmaximum_y-value = %.2f\tthreshold_value = %.2f\tno. of threads = %d\t\n",height,width,max_iterations,min_re,max_re,min_im,max_im,threshold,NUM_OF_THREADS);
for(x = 0; x < height; x++)
{
color[x] = (unsigned int*)malloc(width*sizeof(unsigned int));
}
time_t ts,te;
time(&ts);
method(x,y,height,width,min_re,max_re,min_im,max_im,max_iterations);
time(&te);
double diff = difftime(te,ts);
file_write(width, height);
printf("Total Time elapsed: %f\n",diff);
return 0;
}
How to correct this segmentation fault?
At least one problem is in the file_write function.
unsigned int **color = NULL;
R = (color[y][x]*10);
I assume the color should be an input parameter.
If you are on Linux machine do the following :
$ulimit -c unlimited
Then run the code. Notice a core.[pid] file is generated. fire up gdb like following
$gdb ./your_app core.[pid]
It will take you the statement where segfault occurred. issue a "backtrace" command in gdb prompt to see the call hierarchy.
Remember compiling with "-g" flag to get more verbose gdb output.
There are two major problems with your code:
You allocate memory for the color array but then use a different color inside file_write() which is initialized to NULL.
You need to pass the first color as an argument to file_write():
int main(...)
{
...
file_write(color, width, height);
printf("Total Time elapsed: %f\n",diff);
return 0;
}
And declare the other color as an argument to file_write():
int file_write(unsigned int **color, unsigned int width, unsigned int height)
{
/* unsigned int **color = NULL; // Removed */
...
You're only calling method() once and not storing anything into color. You need to call it in a loop. Something similar to:
/* Untested */
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
color[y][x] = method(x,y,height,width,min_re,max_re,min_im,max_im,max_iterations);
}
}
Then, of course, you should check the return values of malloc(), fopen(), fprintf(), fclose(), ... , and check that the input variables have reasonable values and so on.
I also noticed that you're passing width and height in different order to file_write() and method(). To avoid future headaches, I would change the method() function to method(x, y, width, height) so that the horizontal and vertical arguments are passed in the same order.
I am passing a pointer to function and I want to initialze the array of structures in called function and want to use that array main function. But I was unable to get it in main function.
Here is my code:
typedef struct _testStruct
{
int a;
int b;
} testStruct;
void allocate(testStruct** t)
{
int nCount = 0;
int i = 0;
printf("allocate 1\n");
t = (testStruct**)malloc(10 * sizeof(testStruct));
for(i = 0; i < 10; i++)
{
t[i] = (testStruct *) malloc( 10 * sizeof(testStruct));
}
for(nCount = 0 ; nCount < 10; nCount++)
{
t[nCount]->a = nCount;
t[nCount]->b = nCount + 1;
printf( "A === %d\n", t[nCount]->a);
}
}
int main()
{
int nCount = 0;
testStruct * test = NULL;
int n = 0;
allocate(&test);
for(nCount = 0 ; nCount < 10; nCount++ )
{
if (test == NULL)
{
printf( "Not Allocated\n");
exit(0);
}
//printf("a = %d\n",test[nCount]->a);
/*printf("a = %d\n",test->a);
printf("b = %d\n",test->b); */
}
return 0;
}
Please note I have to pass double pointer to function as it is required.
Thank you for helping.
#include <stdio.h>
#include <stdlib.h>
typedef struct _testStruct
{
int a;
int b;
} testStruct;
void allocate(testStruct** t)
{
int nCount = 0;
printf("allocate 1\n");
testStruct *newT = (testStruct*)malloc(10 * sizeof(testStruct));
for(nCount = 0 ; nCount < 10; nCount++)
{
newT[nCount].a = nCount;
newT[nCount].b = nCount + 1;
printf( "A === %d\n", newT[nCount].a);
}
*t = newT;
}
int main()
{
int nCount = 0;
testStruct * test = NULL;
allocate(&test);
for(nCount = 0 ; nCount < 10; nCount++ )
{
printf("a = %d\n",test[nCount].a);
printf("a = %d\n",test[nCount].b);
}
return 0;
}
Should work.
t = (testStruct**)malloc(10 * sizeof(testStruct));
is assigning to t, not test. Perhaps you want
*t = (testStruct*)malloc(10 * sizeof(testStruct));
instead? I'm not sure, I tend to get lost when so many pointers are around. Anyway, you don't seem to be assigning anything into the pointer you pass to your function.
You say you want to create an array of structures, but your allocate function creates a data structure more like two-dimensional array. In addition, you don't return that structure back to the caller in any way that makes sense. I think you have come confusion about pointers, malloc() and all of the indirection you're doing. Check out #Ed Heal's answer for a corrected program.