hello guys this is my code :
#include <stdio.h>
#include <stdlib.h>
int power(int a, int b) {
int exponent = b, result = 1;
while (exponent != 0) {
result = result * a;
exponent--;
}
//printf("%d",result);
return result;
}
int fill_it(char ** p, int N, int fliptimes, int column2) {
if (N < 0) return 0;
int counter = 0, l;
char a = 'H';
for (l = 0; l < power(2, fliptimes); l++) {
p[l][column2] = a;
counter++;
if (counter == (power(2, N) / 2)) {
counter = 0;
if (a == 'H') a = 'T';
if (a == 'T') a = 'H';
}
}
fill_it(p, N--, fliptimes, column2++);
}
int main() {
int i, fores, j, l, m;
char ** p;
printf("how many times did you toss the coin?:");
scanf("%d", & fores);
p = (char ** ) malloc((power(2, fores)) * sizeof(char * ));
for (i = 0; i < fores; i++)
p[i] = (char * ) malloc(fores * sizeof(char));
fill_it(p, fores, fores, 0);
for (l = 0; l < power(2, fores); l++) {
for (m = 0; m < fores; m++) {
printf("%c", p[l][m]);
}
}
printf(",");
}
it does compile.But when i run the program it returns a "segmantation fault (core dumped)" error
i know it means that i tried to access memory,i dont have acces to but i dont understand which part of the program is defective
The problem is, you're not allocating enough memory. This line is fine
p = (char ** ) malloc((power(2, fores)) * sizeof(char * ));
but this loop is only allocating memory for part of the 2-dimensional array.
for (i = 0; i < fores; i++)
p[i] = (char * ) malloc(fores * sizeof(char));
The memory allocation should look more like this...
foresSquared = power(2, fores);
p = malloc(foresSquared*sizeof(char *));
for (i = 0; i < foresSquared; i++)
p[i] = malloc(fores);
Since the result of power is going to be consistent, it makes sense to store the value in a variable and use that rather than recalculating it. It'll make the code clearer too.
You also don't need to cast the return value of malloc as C handles that for you. And sizeof(char) isn't needed as it's guaranteed to always be 1.
Related
I have to create a function that initializes k cluster choosing the starting center based on the distance between the point.
This is the code i wrote:
int *inizialize_centroids(int *p_dataset, int d, int k, int **p_discard_set) {
int* centroids = (int*) malloc(k*((2*d)+1)*sizeof(int)), *point_to_compare = (int*) malloc(d*sizeof(int)),
*cluster_point = (int*) malloc(d*sizeof(int));
float* distance = (float*) malloc(2*k*sizeof(float));
if(centroids == NULL || point_to_compare == NULL || cluster_point == NULL || distance == NULL){
printf("Something went wrong in inizialize_centroids(), memory allocation failed! (row 94/95)");
exit(1);
}
centroids[0]=1;
for(int i = 1; i < d; i++){
centroids[i] = p_dataset[i];
centroids[i+d] = pow(p_dataset[i],2);
}
*p_discard_set[0] = 1;
*p_discard_set[1] = p_dataset[0];
memcpy(cluster_point, &p_dataset[0], (d + 1)*sizeof(int));
int j;
int i = 1;
int t;
while (i < k){
j = 0;
while(j < 2*CHUNK ){
memcpy(point_to_compare, &p_dataset[j/2 * (d + 1)], (d + 1) * sizeof(int));
distance[j] = (float) point_to_compare[0];
j++;
distance[j] = compare(cluster_point, point_to_compare, i, d);
j++;
}
int id = (int) distance[0];
float max = distance[1];
j = 0;
while (j < 2* CHUNK){
if(distance[j+1] > max){
max = distance[j+1];
id = distance[j];
}
j+=2;
}
i++;
*p_discard_set[0] = i;
*p_discard_set[i] = id; //HERE OCCURE THE PROBLEM
[....]
}
return centroids;
The problem is that, i can't assign
*p_discard_set[i] = id;
and i don't understand why it gives me "interrupted by signal 11: SIGSEGV"
This is how i use it in main:
int *discard_set = (int*) malloc((k + 1) * sizeof(int)), *compressed_set = (int*) malloc(sizeof(int)), *retained_set = (int*) malloc(sizeof(int));
// discard_set è così fatto: [n, id_1, ... , id_n]
if(discard_set == NULL || compressed_set == NULL || retained_set == NULL){
printf("Something went wrong in main(), memory allocation failed! (row 39)");
exit(1);
}
int* centroids = inizialize_centroids(dataset, d, k, &discard_set);
The stange thing is that i can do
*p_discard_set[0] = i;
and k > 2, so it isn't out of bound, I think.
The precedence of postfix operators in C is higher than prefix, so when you say
*p_discard_set[i] = ...
you actually get
*(p_discard_set[i]) = ...
and what you actually want is
(*p_discard_set)[i] = ...
so you need the explicit parentheses to make it work the way you are expecting.
I am having trouble with assigning a return value of a function in heap part of the program. When I tried it in main, it gives an error "Segmentation fault". I believe it is because of the size of my array, which is the return value that I mentioned earlier because when I make my max_size smaller, the code works correctly (I think up to 45000). When I call the function in main, it uses the memory of stack, which is much smaller than memory of heap. Therefore I tried to call the function in heap and make the assignment in there but the compiler gave an error
deneme.c:6:15: error: initializer element is not constant
int *primes = listPrimes(1000000, &size);
After that I did some research and found out that stack is 8 MB memory, which is around 8000000 bytes. Then I estimated my array size as using the prime number theorem (up to 1000000, there are approximately 200000 primes) and sizeof(int) = 4 bit value so it gives 100000 bytes, which is much less than 8 MB. Therefore I have two questions in mind:
1. Why the compiler gives segmentation fault error although my array size is not too large?
2. How can I make the assigment in heap instead of main in order to avoid this problem?
Here is my code:
#include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int *listPrimes(int max_size, int *size) {
*size = 1;
int *result = malloc(*size * sizeof(int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc(max_size*sizeof(int));
for (i = 0; i < max_size; i++) {
nums[i] = i;
}
result[0] = 2;
int j = 2;
while (j < max_size) {
int k = j;
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
if (j == 2) {
j++;
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
else {
j += 2;
if (nums[j] != 0) {
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
}
}
return result;
}
and main function:
#include <stdio.h>
#include <stdlib.h>
#include "mathlib.h"
int size = 0;
int *primes = listPrimes(1000000, &size);
int main() {
printf("size = %d\n", size);
for (int i = 0; i < size; i++) {
printf("%d th prime is %d\n", i+1, primes[i]);
}
free(primes);
return 0;
}
Use unsigned int for j, k and max_size in listPrimes and it works properly . Below is the tested code:
// #include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int size = 0;
int *
listPrimes (unsigned int max_size, int *size)
{
*size = 1;
int *result = malloc (*size * sizeof (int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc (max_size * sizeof (int));
for (i = 0; i < max_size; i++)
{
nums[i] = i;
}
result[0] = 2;
unsigned int j = 2;
while (j < max_size)
{
unsigned int k = j;
while (j * k <max_size)
{
nums[j * k] = 0;
k++;
}
if (j == 2)
{
j++;
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
else
{
j += 2;
if (nums[j] != 0)
{
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
}
}
free(nums);
return result;
}
int
main ()
{
int *primes = listPrimes (1000000, &size);
printf ("size = %d\n", size);
for (int i = 0; i < size; i++)
{
printf ("%d th prime is %d\n", i + 1, primes[i]);
}
free (primes);
return 0;
}
nums is allocated to have max_size elements, so the index of its last element is max-size-1.
This loop:
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
may access an element with index j*k that equals max_size, thus writing beyond the end of the array. The loop should be limited to j*k < max_size.
Regarding your second question, the size of the result array is determined while finding the primes and is not readily calculable in advance, so it cannot easily be allocated prior to calling listPrimes. It could be done by evaluating the prime-counting function, but that is likely more than you want to do for this project.
I want to print kk[i].data[j] but it is not printing at all.
intarr_save_binary is returning 2. I expect to get 0.
int k = sizeof(kk) / sizeof(kk[0]); gives 0. I'm expecting to get 5.
Did I properly allocate the memory?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int len;
int *data;
}intarr_t;
#define MAX 5
intarr_t* intarr_create(unsigned int len) {
intarr_t* new_intarr = (intarr_t*)malloc(sizeof(intarr_t));
if (!new_intarr) return NULL;
new_intarr->data = (int*)malloc(len * sizeof(int));
new_intarr->len = len;
return new_intarr;
}
int intarr_save_binary(intarr_t* ia, const char* filename) {
if (!ia) return 1;
if (!ia->data) return 2;
FILE* f = fopen(filename, "w");
if (!f) return 3;
if (fwrite(&ia->len, sizeof(ia->len), 1, f) == 1) {
fprintf(f, "%d ", ia->len);
}
else {
return 4;
}
if (fwrite(ia->data, sizeof(ia->data), ia->len, f) == ia->len) {
fclose(f);
return 0;
}
else {
fclose(f);
return 5;
}
}
int main() {
intarr_t *ia = (intarr_t*)malloc(MAX*sizeof(intarr_t));
int i;
int j;
for (j = 0; j < MAX; j++) {
ia[j].len = j + 1;
}
for (j = 0; j < MAX; j++) {
ia[j].data = (int*)malloc(ia[j].len * sizeof(int));
}
for (j = 0; j < MAX; j++) {
for (i = 0; i < ia[j].len; i++) {
ia[j].data = (i + 1) * j;
}
}
char name[20] = "myfile.txt";
int d;
printf("%d \n", intarr_save_binary(ia, name));
intarr_t *kk;
kk = intarr_create(MAX);
int k = sizeof(kk) / sizeof(kk[0]);
printf("%d\n",k);
for (j = 0; j < k; j++) {
for (i = 0; i < kk[j].len; i++) {
printf("%d: %d\n", i, kk[j].data[i]);
}
printf("\n");
}
free(kk);
return 0;
}
intarr_save_binary is returning 2. I expect to get 0.
for (j = 0; j < MAX; j++) {
for (i = 0; i < ia[j].len; i++) {
ia[j].data = (i + 1) * j;
}
}
This zeroes ia[0].data on the very first pass through the double loop. (ia[0].data = (0 + 1) * 0 gives 0).
Thus ia->data is 0, and !ia->data is true, making the function return 2.
int k = sizeof(kk) / sizeof(kk[0]); gives 0. I'm expecting to get 5.
You obviously expect sizeof kk to give the total amount of memory allocated for kk.
And that is what you get, actually -- the total amount of memory allocated for intarr_t *, which is the type of kk at that point. That most likely results in 4 or 8, depending on your architecture. What it is not is whatever len * sizeof(int) resulted in when you called intarr_create(). As #BoPersson commented, if you allocate the memory yourself, you have to remember yourself how much you allocated.
The sizeof kk / sizeof kk[0] "trick" only works if kk actually is an array, i.e. if it has been declared as such within the scope of you using the sizeof operator on it so the compiler can "see" its size.
So, as you have an int and an int * in your struct kk[0], which together are very likely to require more memory than an intarr_t *, the integer division results in 0.
You might also take note that free() is not recursive. With free(kk), you are leaking all the memory you allocated for all the data members. For every malloc(), there needs to be a corresponding free(). (And it does matter even if the program ends right after that one free(), as not all operating systems can / will protect you from this error.)
I am working on a custom malloc and free implementation in C. My code works fine, but not perfectly. In my file that tests my_malloc and my_free, I call my_malloc 3 times. It works for the first 2 calls, but doesn't for the 3rd call. Everything is exactly the same, so I really have no idea why it wouldn't work again. I know there's enough memory in the heap, so it's not that. It even works to the point of returning an address for the pointer variable, but the test file won't write to it.
Here's the bit of code to test my_malloc and my_free, it breaks with c:
static int *base;
static int *heap_end;
int total_mem_used = 0;
int first_call = 1;
int i;
int *a, *b, *c;
if ((a=(int *)my_malloc(10))==NULL)
return MALLOC_FAIL;
for (i=0;i<10;i++)
a[i] = i;
for (i=0;i<10;i++)
printf("%d\n", a[i]);
if ((b=(int *)my_malloc(18))==NULL)
return MALLOC_FAIL;
for (i=0;i<18;i++)
b[i] = i*i;
for (i = 0; i < 18; i++)
printf("%d ", b[i]);
printf("\n");
if ((c=(int *)my_malloc(5))==NULL)
return MALLOC_FAIL;
for (i=0;i<5;i++)
c[i] = i*7;
Here's my_malloc too, if it helps:
void *p;
int *t;
int data_size, block;
if (size==0)
return NULL;
if (first_call) {
if ((base=(int *)malloc(HEAP_SIZE))==NULL)
return NULL;
init_heap(norm_size(size)+8);
heap_end = &base[HEAP_SIZE];
first_call = 0;
total_mem_used += (norm_size(size)+2);
t = base;
return (void *) (t+2);
}
data_size = norm_size(size);
block = data_size + 2;
p = find_first_free(block);
if (p==0) {
errno = ENOMEM;
return NULL;
}
total_mem_used += block;
fill_header((int *) p, block);
t = (int *) p + 2;
return (void *) t;
void my_free(void *p) {
int *t;
t = (int *) p - 2;
*t = *t & -2;
coalesce(t);
}
void *find_first_free(int n) {
int *p;
p = base;
while (p<heap_end && ((*p & 1) || (*p <= n)))
p = p + (*p & -2);
return (void *)p;
}
int norm_size(int w) {
if (w % 8 == 0)
return w;
else
return w + (8 - w % 8);
}
void init_heap(int n) {
base[0] = n+1; // n+1 since we're allocating it
base[1] = (int) &base[n];
base[n-1] = n+1;
base[n] = HEAP_SIZE - n;
base[HEAP_SIZE-1] = HEAP_SIZE - n;
}
void fill_header(int *p, int w) {
p[0] = w+1;
p[1] = (int) &p[w];
p[w-1] = w+1;
p[w] = HEAP_SIZE - total_mem_used;
p[w+HEAP_SIZE-total_mem_used-1] = HEAP_SIZE - total_mem_used;
}
Any idea what exactly is wrong with the program? Thanks for any help.
Avoid magic numbers
block = data_size + 2;
Why 2? why not 16 or 256? Certainly the addition is done to provide for saving the size. In that case, add the size of the int.
block = data_size + sizeof(int);
t = (int *) p + 2;
Why 2 versus any other number? Again, this is done to account for the size begin saved at p. But this is not integer addition like before. This is "pointer addition". With + 2, p is increased by the 2 * sizeof(int). Likely code should be
t = p + 1;
This is an exception to the "no magic numbers" rule: -1,0,+1 are OK
To answer more, post complete functions.
Minor: cast not needed
// if ((base=(int *)malloc(HEAP_SIZE))==NULL)
if ((base = malloc(HEAP_SIZE)) == NULL)
Minor: Consider the unsigned type size_t. That is the type returned by functions/operators like strlen(), sizeof()
// int data_size
size_t data_size
// if ((a=(int *)my_malloc(10))==NULL)
a = my_malloc(10);
if (a == NULL)
Why 8 in init_heap(norm_size(size)+8);? Use a constant/define
#define MY_MALLOC_GUARD (8)
init_heap(norm_size(size) + MY_MALLOC_GUARD);
I'm having problems understanding how to write code that solves the following problem: I have a structure containing a 2D-array. Then I have a recursive function that take a pointer to the structure as an argument and I want the recursive function to be able to manipulate the structure sent, not a local copy.
The struct is initialized in the function initStruct, where memory for the 2D-array is allocated. The recursive function builds up an array and at a specific point calls a function to insert it into the structure's array.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int** spBasis(int);
void mpBasis(int**, int, int, int, int, int, int, int*, struct mpBasis *, int, int);
void initMpBasis(struct mpBasis *, int, int);
void insertMpState(struct mpBasis *, int *);
struct mpBasis {
int** basis;
int size;
int capacity;
};
int main() {
int a, b, c, d;
char maxE[256];
char noParticles[256];
char P[256];
char M[256];
FILE *fp;
int **spStates;
struct mpBasis *mp;
int mpState[6] = {0, 0, 0, 0, 0, 0};
printf("Input max e for sp states, no of particles, parity (1 for odd and 0 for even) and magnetic projection: ");
gets(maxE);
gets(noParticles);
gets(P);
gets(M);
spStates = spBasis(atoi(maxE));
fp = fopen("spStates.txt", "a+");
fprintf(fp, "E\tj\tl\tm\n");
for (a = 0; a < 330; a++) {
fprintf(fp, "State %d: ", a+1);
for (b = 0; b < 4; b++) {
fprintf(fp, "%d\t", spStates[a][b]);
}
fprintf(fp, "\n");
}
mp = malloc(sizeof(struct mpBasis));
initMpBasis(mp, 5449, 6);
for (c = 0; c < 5449; c++) {
for (d = 0; d < 6; d++) {
fprintf(fp, "%d: %d\t", c, mp->basis[c][d]);
}
fprintf(fp, "\n");
}
printf("%p\n", (void*) mp);
printf("hello 3");
mpBasis(spStates, 0, atoi(maxE), 0, atoi(M), 0, atoi(P), mpState, mp, 0, 0);
fclose(fp);
return 0;
}
int** spBasis(int maxE) {
int c;
int i, j, k, l;
int q = 0;
int** spStates;
spStates = (int**)malloc(330 * sizeof(int *));
for (c = 0; c < 330; c++) {
spStates[c] = malloc(4 * sizeof(int));
}
for (i = 0; i <= maxE; i++) {
for (j = i % 2; j <= i; j += 2) {
for (k = -(2 * j + 1); k <= (2 * j + 1); k += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j + 1;
spStates[q][3] = k;
q += 1;
}
for (l = -(2 * j - 1); l <= (2 * j - 1); l += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j - 1;
spStates[q][3] = l;
q += 1;
}
}
}
return spStates;
}
void mpBasis(int** spStates, int e, int maxE, int m, int M, int l,
int P, int * mpState, struct mpBasis *mpB, int position, int lastSpState) {
int i;
for (i = lastSpState; i < 330; i++) {
if (e > maxE) {
break;
} else if (position == 5) {
if (m == M && l % 2 == P) {
insertMpState(mpB, mpState);
break;
}
} else {
// add spState to mpState and make the recursive call for the next position
mpState[position] = i;
mpBasis(spStates, e + spStates[i][0], maxE, m + spStates[i][3], M,
l + spStates[i][1], P, mpState, mpB, position+1, i);
}
}
}
void initMpBasis(struct mpBasis *a, int initialSize, int sizeY) {
int c;
a->basis = (int **)malloc(initialSize * sizeof(int*));
for (c = 0; c < initialSize; c++) {
a->basis[c] = (int *) malloc(sizeY * sizeof(int));
}
a->size = 0;
a->capacity = initialSize;
}
void insertMpState(struct mpBasis *a, int* mpState) {
/*if (a->size == a->capacity) {
a->size *= 2;
a->basis = (int **)realloc(a->basis, a->size * sizeof(int));
}*/
a->basis[a->size++] = mpState;
}
Added all the code.
The problem is that after the recursive function has been called, the "basis" array in structure mpBasis still only contains random values, i.e. the mpBasis function hasn't done anything with it. Am I passing the mp argument by value here?
Thanks for your help!
The first step is to compile with warnings enabled. Eg if you are using GCC you can use option -Wall -Wextra.
EDIT:
(previous listing of >20 errors removed)
Ok, since you are using Visual Studio, enable warnings like this:
Open the project's Property Pages dialog box.
Select C/C++.
On the General property page, modify the Warning Level to /W4