I am trying to work with directly with some low level memory stuff. I am filling a buffer with some data and then copying it to a larger buffer.
I wrote this function to help with some float data:
void copy_float_buffer(void* dest, size_t dest_index, void* src,
size_t src_index, size_t num_to_copy) {
memcpy(&dest[dest_index], &src[src_index], num_to_copy * sizeof(float));
}
I currently have two different buffers and two of each type.
float buffa[12]; // i have two of these
float buffb[12]; // and two of these as well
Then have two larger buffers that will hold the those buffers back to back.
float buffera[24]; //holds 2 buffa
float bufferb[24] //holds 2 buffb
I have simple for loop that does some calculate and fills buffa and buffb then I use the copy_float_buffers command to fill in the buffers. I do it like this.
typedef struct {
float buffa[12];
float buffb[12];
} buffs;
buffs* b;
for (int j = 0; j < 2; j++) {
b = calloc(1, sizeof(buffs));
}
for (int i = 0; i < 12; i++) {
b->buffa[i] = vmathRandRange(21);
b->buffb[i] = vmathRandRange(21);
}
for (int i = 0; i < 12; i++) {
/* printf("index:%d value:%f \n", i, b->buffa[i]); */
/* b->buffa[i] = vmathRandRange(21); */
copy_float_buffer(v_buff, (sizeof(float) * i) * 12, b->buffa,
(sizeof(float) * i) * 12, 12);
copy_float_buffer(v_buff, (sizeof(float) * i) * 12, b->buffb,
(sizeof(float) * i) * 12, 12);
}
print_buffer(b->buffa, "original buffer");
print_buffer(v_buff, "vertex buffer");
print_buffer(b->buffb, "original buffer");
print_buffer2(v_buff, "vertex buffer");
the print_buffers function just loops for 0-11 or 12-22 and prints out the values.
I feel like this is a pointer math issue and I was using gdb to try and look at the code and see how it's being copied over but I get that error above.
Attempt to dereference a generic pointer.
how do I dereference pointers when stepping through code in gdb and also. I think that function to do the memory copy is setup correctly. But it seems to be only overwriting the first 12 float or first 48 bytes and not actually shifting, something like a ring buffer.
As already mentioned in comments, you can't do dest[dest_index] simply because dest is a void*
Your copy function seems strange. In the main-code you spend a lot of effort calculating byte offsets but still you use sizeof(float) inside the copy_float_buffer function. You should either write the function to use floats everywhere or bytes everywhere - that will be much easier to understand.
Since the function is called copy_float_buffer it indicates that you want to copy floats, so it should be:
void copy_float_buffer(float* dest, size_t dest_index, float* src,
size_t src_index, size_t num_to_copy) {
memcpy(&dest[dest_index], &src[src_index], num_to_copy * sizeof(float));
}
to copy num_to_copy floats. If you do like this, you need to change the way you call the function, i.e. get rid of all the byte-offset calculation. Something like:
copy_float_buffer(v_buff, 0, b->buffa, 0, 12); // Ends in v_buff[0..11]
^ ^ ^
| | Copy 12 floats
| Start offset in buffa
Start offset in v_buff
copy_float_buffer(v_buff, 12, b->buffb, 0, 12); // Ends in v_buff[12..23]
^ ^ ^
| | Copy 12 floats
| Start offset in buffb
Start offset in v_buff
The rest of your code have some issues as well:
// You loop twice but simply overwrite `b` the second time
// so you leak memory
for (int j = 0; j < 2; j++) {
b = calloc(1, sizeof(buffs));
}
// Why do you loop 12 times?
// Do you want to copy the data in to the main buffer 12 times?
for (int i = 0; i < 12; i++) {
// The two call of copy_float_buffer is identical except for buffa and buffb
// So buffb will overwrite buffa
// Probably not what you want or ...?
copy_float_buffer(v_buff, (sizeof(float) * i) * 12, b->buffa,
(sizeof(float) * i) * 12, 12);
copy_float_buffer(v_buff, (sizeof(float) * i) * 12, b->buffb,
(sizeof(float) * i) * 12, 12);
}
Related
I've been reading up on the use of pointers, and allocating memory for embedded projects. I must admit, that i perhaps don't understand it fully, as i can't seem to figure where my problem lies.
My two functions are supposed to take 4 float values, and return 16 bytes, that represent these, in order to transfer them through SPI. It works great, but only for a minute, before the program crashes and my SPI and I2C dies, lol.
Here are the functions:
/*Function that wraps a float value, by allocating memory and casting pointers.
Returns 4 bytes that represents input float value f.*/
typedef char byte;
byte* floatToByteArray(float f)
{
byte* ret = malloc(4 * sizeof(byte));
unsigned int asInt = *((int*)&f);
int i;
for (i = 0; i < 4; i++) {
ret[i] = (asInt >> 8 * i) & 0xFF;
}
return ret;
memset(ret, 0, 4 * sizeof(byte)); //Clear allocated memory, to avoid taking all memory
free(ret);
}
/*Takes a list of 4 quaternions, and wraps every quaternion in 4 bytes.
Returns a 16 element byte list for SPI transfer, that effectively contains the 4 quaternions*/
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
uint8_t m;
uint8_t n;
uint8_t k = 0;
for (m = 0; m < 4; m++)
{
for (n = 0; n < 4; n++)
{
byte* asBytes = floatToByteArray(Quaternion[m]);
buff[n+4*k] = asBytes[n];
}
k++;
}
}
The error message i receive after is the following, in the disassembly window of Atmel Studio
Atmel studio screenshot
You might drop all the dynamic memory allocation completely.
void floatToByteArray(float f, byte buf[4])
{
memcpy(buf, &f, sizeof(f));
}
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
for (int i = 0; i < 4; i++)
{
floatToByteArray(Quaternion[i], &buf[4*i]);
}
}
With this approach you do not need to care about freeing allocated memory after use. It is also much more efficient because dynamic memory allocation is rather expensive.
Gerhardh is correct, return prevent the memory from being released.
If you need to return 4 bytes, you might check if your environment can return a uint32_t or something like that.
As already mentioned, the lines below return ret; are never executed. And anyway if you want to return allocated memory in a function (what is fine) you can't free it in the function itself but it has to be freed by the caller when it isn't needed anymore. So your calling function should look like
/*Takes a list of 4 quaternions, and wraps every quaternion in 4 bytes.
Returns a 16 element byte list for SPI transfer, that effectively contains the 4 quaternions*/
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
uint8_t m;
uint8_t n;
uint8_t k = 0;
for (m = 0; m < 4; m++)
{
byte* asBytes = floatToByteArray(Quaternion[m]); // no need it to call for every n
for (n = 0; n < 4; n++)
{
buff[n+4*k] = asBytes[n];
}
free(asBytes); // asBytes is no longer needed and can be free()d
k++;
}
}
regarding:
buff[n+4*k] = asBytes[n];
This results in:
buff[0] << asBytes[0] // from first call to `byte* floatToByteArray(float f)`
buff[4] << asBytes[1] // from second call to `byte* floatToByteArray(float f)`
buff[8] << asBytes[2] // from third call to `byte* floatToByteArray(float f)`
buff[12] << asBytes[3] // from forth call to `byte* floatToByteArray(float f)`
most of the above problem can be fixed by using memcpy() to copy the 4 bytes from asBytes[] to buff[] similar to:
memcpy( &buff[ n*4 ], asBytes, 4 );
Of course, there is also the consideration: Is the length of a float, on your hardware/compiler actually 4 bytes.
'magic' numbers are numbers with no basis. 'magic' numbers make the code much more difficult to understand, debug, etc. I.E. 4. Suggest using something like: length = sizeof( float ); then using length everywhere that 4 is currently being used, except for the number of entries in the Quaternion[] array. for that 'magic' number, strongly suggest the statement: #define arraySize 4 be early in your code. Then using arraySize each time the code references the number of elements in the array
I'm working on a C implementation for Conway's game of life, I have been asked to use the following header:
#ifndef game_of_life_h
#define game_of_life_h
#include <stdio.h>
#include <stdlib.h>
// a structure containing a square board for the game and its size
typedef struct gol{
int **board;
size_t size;
} gol;
// dynamically creates a struct gol of size 20 and returns a pointer to it
gol* create_default_gol();
// creates dynamically a struct gol of a specified size and returns a pointer to it.
gol* create_gol(size_t size);
// destroy gol structures
void destroy_gol(gol* g);
// the board of 'g' is set to 'b'. You do not need to check if 'b' has a proper size and values
void set_pattern(gol* g, int** b);
// using rules of the game of life, the function sets next pattern to the g->board
void next_pattern(gol* g);
/* returns sum of all the neighbours of the cell g->board[i][j]. The function is an auxiliary
function and should be used in the following function. */
int neighbour_sum(gol* g, int i, int j);
// prints the current pattern of the g-board on the screen
void print(gol* g);
#endif
I have added the comments to help out with an explanation of what each bit is.
gol.board is a 2-level integer array, containing x and y coordinates, ie board[x][y], each coordinate can either be a 1 (alive) or 0 (dead).
This was all a bit of background information, I'm trying to write my first function create_default_gol() that will return a pointer to a gol instance, with a 20x20 board.
I then attempt to go through each coordinate through the 20x20 board and set it to 0, I am getting a Segmentation fault (core dumped) when running this program.
The below code is my c file containing the core code, and the main() function:
#include "game_of_life.h"
int main()
{
// Create a 20x20 game
gol* g_temp = create_default_gol();
int x,y;
for (x = 0; x < 20; x++)
{
for (y = 0; y < 20; y++)
{
g_temp->board[x][y] = 0;
}
}
free(g_temp);
}
// return a pointer to a 20x20 game of life
gol* create_default_gol()
{
gol* g_rtn = malloc(sizeof(*g_rtn) + (sizeof(int) * 20 * 20));
return g_rtn;
}
This is the first feature I'd like to implement, being able to generate a 20x20 board with 0's (dead) state for every coordinate.
Please feel free to criticise my code, I'm looking to determine why I'm getting the segmentation fault, and if I'm allocating memory properly in the create_default_gol() function.
Thanks!
The type int **board; means that board must contain an array of pointers, each of which points to the start of each row. Your existing allocation omits this, and just allocates *g_rtn plus the ints in the board.
The canonical way to allocate your board, supposing that you must stick to the type int **board;, is:
gol* g_rtn = malloc(sizeof *g_rtn);
g_rtn->size = size;
g_rtn->board = malloc(size * sizeof *g_rtn->board);
for (int i = 0; i < size; ++i)
g_rtn->board[i] = malloc(size * sizeof **g_rtn->board);
This code involves a lot of small malloc chunks. You could condense the board rows and columns into a single allocation, but then you also need to set up pointers to the start of each row, because board must be an array of pointers to int.
Another issue with this approach is alignment. It's guaranteed that a malloc result is aligned for any type; however it is possible that int has stricter alignment requirements than int *. My following code assumes that it doesn't; if you want to be portable then you could add in some compile-time checks (or run it and see if it aborts!).
The amount of memory required is the sum of the last two mallocs:
g_rtn->board = malloc( size * size * sizeof **g_rtn->board
+ size * sizeof *g_rtn->board );
Then the first row will start after the end of the row-pointers (a cast is necessary because we are converting int ** to int *, and using void * means we don't have to repeat the word int):
g_rtn->board[0] = (void *) (g_rtn->board + size);
And the other rows each have size ints in them:
for (int i = 1; i < size; ++i)
g_rtn->board[i] = g_rtn->board[i-1] + size;
Note that this is a whole lot more complicated than just using a 1-D array and doing arithmetic for the offsets, but it was stipulated that you must have two levels of indirection to access the board.
Also this is more complicated than the "canonical" version. In this version we are trading code complexity for the benefit of having a reduced number of mallocs. If your program typically only allocates one board, or a small number of boards, then perhaps this trade-off is not worth it and the canonical version would give you fewer headaches.
Finally - it would be possible to allocate both *g_rtn and the board in the single malloc, as you attempted to do in your question. However my advice (based on experience) is that it is simpler to keep the board separate. It makes your code clearer, and your object easier to use and make changes to, if the board is a separate allocation to the game object.
create_default_gol() misses to initialise board, so applying the [] operator to it (in main() ) the program accesses "invaid" memory and with ethis provokes undefined behaviour.
Although enough memory is allocated, the code still needs to make board point to the memory by doing
gol->board = ((char*) gol) + sizeof(*gol);
Update
As pointed out by Matt McNabb's comment board points to an array of pointers to int, so initialisation is more complicate:
gol * g_rtn = malloc(sizeof(*g_rtn) + 20 * sizeof(*gol->board));
g_rtn->board = ((char*) gol) + sizeof(*gol);
for (size_t i = 0; i<20; ++i)
{
g_rtn->board[i] = malloc(20 * sizeof(*g_rtn->board[i])
}
Also the code misses to set gol's member size. From what you tell us it is not clear whether it shall hold the nuber of bytes, rows/columns or fields.
Also^2 coding "magic numbers" like 20 is bad habit.
Also^3 create_default_gol does not specify any parameters, which explictily allows any numberm and not none as you might perhaps have expected.
All in all I'd code create_default_gol() like this:
gol * create_default_gol(const size_t rows, const size_t columns)
{
size_t size_rows = rows * sizeof(*g_rtn->board));
size_t size_column = columns * sizeof(**g_rtn->board));
gol * g_rtn = malloc(sizeof(*g_rtn) + size_rows);
g_rtn->board = ((char*) gol) + sizeof(*gol);
if (NULL ! = g_rtn)
{
for (size_t i = 0; i<columns; ++i)
{
g_rtn->board[i] = malloc(size_columns); /* TODO: Add error checking here. */
}
g_rtn->size = size_rows * size_columns; /* Or what ever this attribute is meant for. */
}
return g_rtn;
}
gol* create_default_gol()
{
int **a,i;
a = (int**)malloc(20 * sizeof(int *));
for (i = 0; i < 20; i++)
a[i] = (int*)malloc(20 * sizeof(int));
gol* g_rtn = (gol*)malloc(sizeof(*g_rtn));
g_rtn->board = a;
return g_rtn;
}
int main()
{
// Create a 20x20 game
gol* g_temp = create_default_gol();
int x,y;
for (x = 0; x < 20; x++)
{
for (y = 0; y < 20; y++)
{
g_temp->board[x][y] = 10;
}
}
for(x=0;x<20;x++)
free(g_temp->board[x]);
free(g_temp->board);
free(g_temp);
}
main (void)
{
gol* gameOfLife;
gameOfLife = create_default_gol();
free(gameOfLife);
}
gol* create_default_gol()
{
int size = 20;
gol* g_rtn = malloc(sizeof *g_rtn);
g_rtn = malloc(sizeof g_rtn);
g_rtn->size = size;
g_rtn->board = malloc(size * sizeof *g_rtn->board);
int i, b;
for (i = 0; i < size; ++i){
g_rtn->board[i] = malloc(sizeof (int) * size);
for(b=0;b<size;b++){
g_rtn->board[i][b] = 0;
}
}
return g_rtn;
}
Alternatively, since you also need to add a create_gol(size_t new_size) of custom size, you could also write it as the following.
main (void)
{
gol* gameOfLife;
gameOfLife = create_default_gol();
free(gameOfLife);
}
gol* create_default_gol()
{
size_t size = 20;
return create_gol(size);
}
gol* create_gol(size_t new_size)
{
gol* g_rtn = malloc(sizeof *g_rtn);
g_rtn = malloc(sizeof g_rtn);
g_rtn->size = new_size;
g_rtn->board = malloc(size * sizeof *g_rtn->board);
int i, b;
for (i = 0; i < size; ++i){
g_rtn->board[i] = malloc(sizeof (int) * size);
for(b=0;b<size;b++){
g_rtn->board[i][b] = 0;
}
}
return g_rtn;
}
Doing this just minimizes the amount of code needed.
I want to implement a convolution function to use in mean filter and gaussian filter and I need to implement those 2 filters as well to apply to pgm files.
I have
typedef struct _PGM{
int row;
int col;
int max_value;
int **matrix;
}PGM;
struct and
int convolution(int ** kernel,int ksize, PGM * image, PGM * output){
int i, j, x, y;
int sum;
int data;
int scale =ksize*ksize;
int coeff;
for (x=ksize/2; x<image->row-ksize/2;++x) {
for (y=ksize/2; y<image->col-ksize/2; ++y){
sum = 0;
for (i=-ksize/2; i<=ksize/2; ++i){
for (j=-ksize/2; j<=ksize/2; ++j){
data = image->matrix[x +i][y +j];
coeff = kernel[i+ksize/2][j+ksize/2];
sum += data * coeff;
}
}
output->matrix[x][y] = sum / scale;
}
}
return sum/scale;
}
convolution function but I get error(actually it terminates) in convolution function so I could not proceed to filter
Can you help me with the implementation ?
Thank you.
In your convolution there are two things wrong that probably aren't causing the crash. The first is style: You're using x to iterate over the rows of an image, something I picture more as a y displacement, and vice-versa. The second is that when you're computing the sum, you're not resetting the variable sum = 0 prior to evaluating the kernel (the inner two loops) for each pixel. Instead you accumulate sum over all pixels, probably eventually causing integer overflow. While strictly speaking this is UB and could cause a crash, it's not the issue you're facing.
If you would kindly confirm that the crash occurs on the first pixel (x = ksize/2, y = ksize/2), then since the crash occurs at the first coefficient read from the kernel, I suspect you may have passed the "wrong thing" as the kernel. As presented, the kernel is an int**. For a kernel size of 3x3, this means that to call this function correctly, you must have allocated on the heap or stack an array of int*, where you stored 3 pointers to int arrays with 3 coefficients each. If you instead passed a int[3][3] array, the convolution function will attempt to interpret the first one or two int in the array as a pointer to an int when it is not, and try to dereference it to pull in the coefficient. This will most likely cause a segfault.
I also don't know why you are returning the accumulated sum. This isn't a "traditional" output of convolution, but I surmise you were interested in the average brightness of the output image, which is legitimate; In this case you should use a separate and wider integer accumulator (long or long long) and, at the end, divide it by the number of pixels in the output.
You probably found the PGM data structure from the internet, say, here. Allow me to part with this best-practice advice. In my field (computer vision), the computer vision library of choice, OpenCV, does not express a matrix as an array of row pointers to buffers of col elements. Instead, a large slab of memory is allocated, in this case of size image->row * image->col * sizeof(int) at a minimum, but often image->row * image->step * sizeof(int) where image->step is image->col rounded up to the next multiple of 4 or 16. Then, only a single pointer is kept, a pointer to the base of the entire image, although an extra field (the step) has to be kept if images aren't continuous.
I would therefore rework your code thus:
/* Includes */
#include <stdlib.h>
/* Defines */
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
/* Structure */
/**
* Mat structure.
*
* Stores the number of rows and columns in the matrix, the step size
* (number of elements to jump from one row to the next; must be larger than or
* equal to the number of columns), and a pointer to the first element.
*/
typedef struct Mat{
int rows;
int cols;
int step;
int* data;
} Mat;
/* Functions */
/**
* Allocation. Allocates a matrix big enough to hold rows * cols elements.
*
* If a custom step size is wanted, it can be given. Otherwise, an invalid one
* can be given (such as 0 or -1), and the step size will be chosen
* automatically.
*
* If a pointer to existing data is provided, don't bother allocating fresh
* memory. However, in that case, rows, cols and step must all be provided and
* must be correct.
*
* #param [in] rows The number of rows of the new Mat.
* #param [in] cols The number of columns of the new Mat.
* #param [in] step The step size of the new Mat. For newly-allocated
* images (existingData == NULL), can be <= 0, in
* which case a default step size is chosen; For
* pre-existing data (existingData != NULL), must be
* provided.
* #param [in] existingData A pointer to existing data. If NULL, a fresh buffer
* is allocated; Otherwise the given data is used as
* the base pointer.
* #return An allocated Mat structure.
*/
Mat allocMat(int rows, int cols, int step, int* existingData){
Mat M;
M.rows = max(rows, 0);
M.cols = max(cols, 0);
M.step = max(step, M.cols);
if(rows <= 0 || cols <= 0){
M.data = 0;
}else if(existingData == 0){
M.data = malloc(M.rows * M.step * sizeof(*M.data));
}else{
M.data = existingData;
}
return M;
}
/**
* Convolution. Convolves input by the given kernel (centered) and stores
* to output. Does not handle boundaries (i.e., in locations near the border,
* leaves output unchanged).
*
* #param [in] input The input image.
* #param [in] kern The kernel. Both width and height must be odd.
* #param [out] output The output image.
* #return Average brightness of output.
*
* Note: None of the image buffers may overlap with each other.
*/
int convolution(const Mat* input, const Mat* kern, Mat* output){
int i, j, x, y;
int coeff, data;
int sum;
int avg;
long long acc = 0;
/* Short forms of the image dimensions */
const int iw = input ->cols, ih = input ->rows, is = input ->step;
const int kw = kern ->cols, kh = kern ->rows, ks = kern ->step;
const int ow = output->cols, oh = output->rows, os = output->step;
/* Kernel half-sizes and number of elements */
const int kw2 = kw/2, kh2 = kh/2;
const int kelem = kw*kh;
/* Left, right, top and bottom limits */
const int l = kw2,
r = max(min(iw-kw2, ow-kw2), l),
t = kh2,
b = max(min(ih-kh2, oh-kh2), t);
/* Total number of pixels */
const int totalPixels = (r-l)*(b-t);
/* Input, kernel and output base pointers */
const int* iPtr = input ->data;
const int* kPtr = kern ->data + kw2 + ks*kh2;
int* oPtr = output->data;
/* Iterate over pixels of image */
for(y=t; y<b; y++){
for(x=l; x<r; x++){
sum = 0;
/* Iterate over elements of kernel */
for(i=-kh2; i<=kh2; i++){
for(j=-kw2; j<=kw2; j++){
data = iPtr[j + is*i + x];
coeff = kPtr[j + ks*i ];
sum += data * coeff;
}
}
/* Compute average. Add to accumulator and store as output. */
avg = sum / kelem;
acc += avg;
oPtr[x] = avg;
}
/* Bump pointers by one row step. */
iPtr += is;
oPtr += os;
}
/* Compute average brightness over entire output */
if(totalPixels == 0){
avg = 0;
}else{
avg = acc/totalPixels;
}
/* Return average brightness */
return avg;
}
/**
* Main
*/
int main(int argc, char* argv[]){
/**
* Coefficients of K. Binomial 3x3, separable. Unnormalized (weight = 16).
* Step = 3.
*/
int Kcoeff[3][3] = {{1, 2, 1}, {2, 4, 2}, {1, 2, 1}};
Mat I = allocMat(1920, 1080, 0, 0);/* FullHD 1080p: 1920x1080 */
Mat O = allocMat(1920, 1080, 0, 0);/* FullHD 1080p: 1920x1080 */
Mat K = allocMat( 3, 3, 3, &Kcoeff[0][0]);
/* Fill Mat I with something.... */
/* Convolve with K... */
int avg = convolution(&I, &K, &O);
/* Do something with O... */
/* Return */
return 0;
}
Reference: Years of experience in computer vision.
int getbit(int * list, int n)
{
return (list[n / 32] >> (n % 32)) & 1;
}
void setbit(int * list, int n)
{
list[n / 32] |= 1 << (n % 32);
}
int main()
{
FILE * out;
int size = 99; //2000000000;
int root = sqrt(size);
int * list = malloc(size / 8.0); //(2*10^9)/8
memset(list, 0, sizeof list);
int i, j;
for (i = 2; i <= root; i++)
for (j = 2 * i; j < size; j += i)
setbit(list, j);
printf("i=%d j=%d 98=%d\n", i, j, getbit(list, 98));
out = fopen("output.txt", "w");
printf("i=%d j=%d 98=%d\n", i, j, getbit(list, 98));
/*for (i=2; i<size; i++)
if (!getbit(list, i))
fprintf(out, "%d\n", i);
fclose(out);*/
return 0;
}
Whenever I use the fopen() in between printf, the value of the third parameter changes from 1 to 0. If I comment out the line then the value is same. What might be the reason behind this?
You see undefined behavior: sizeof(list) is probably 4 or 8 bytes, depending on the architecture, so memset with zeros does not go past the forth byte. You are reading from the third 32-bit word, which came from malloc and has not been initialized by the memset yet. Moreover, you are allocating 12 bytes (size/8.0 gets converted to int; it never makes sense to pass a float or a double to malloc, because you cannot allocate fractional bytes) so accessing the 98-th bit goes past the allocated area.
You should fix these undefined behaviors: allocate enough memory by using
// count needs to be a multiple of sizeof(int)
// The math gets pretty ugly here, but it should work:
int count = sizeof(int)*(size+(8*sizeof(int))-1)/(8*sizeof(int));
int * list = malloc(count);
Then initialize the data to zero by using the proper size:
memset(list, 0, count);
You're writing in memory you do not own, that has an undefined behavior.
Firstly, you're allocating only 12 bytes here:
int* list = malloc(size / 8.0);
You should do this (just giving you the idea, I don't know how many bytes you really want to allocate..):
int* list = malloc((size / 8.0) * sizeof(*list));
Secondly, you are memsetting only 4 bytes (if you're on 32bits system) here:
memset(list, 0, sizeof list);
You should do this:
memset(list, 0, (size / 8.0) * sizeof(*list));
Finally, the only reason your call to fopen() changes things, is because fopen() allocates memory.
Good luck.
I have been stuck on this for a while and nothing seems to work.
I have a data structure:
DATA
{
int size;
int id;
}
And I have an array of DATA structures:
myArray = (DATA *) malloc(10 * sizeof(DATA));
Then I assign some test values:
myArray[0].size = 5;
myArray[1].size = 9;
myArray[2].size = 1;
myArray[3].size = 3;
So my starting array should look like:
5,9,1,3,0,0,0,0,0,0
Then, I call qsort(myArray,10,sizeof(DATA),comp)
Where comp is:
int comp(const DATA * a, const DATA * b)
{
return a.size - b.size;
}
And trust me, I tried many things with the compare function, NOTHING seems to work. I just never get any sorting that makes any sense.
So my starting array should look like 5, 9, 1, 3, 0, 0, 0, 0, 0, 0.
No, it really won't, at least it's not guaranteed to.
If you want zeros in there, either use calloc() to zero everything out, or put them in yourself. What malloc() will give you is a block of the size required that has indeterminant content. In other words, it may well have whatever rubbish was in memory beforehand.
And, on top of that, a and b are pointers in your comp function, you should be using -> rather than . and it's good form to use the correct prototype with casting.
And a final note: please don't cast the return from malloc in C - you can get into problems if you accidentally forget to include the relevant header file and your integers aren't compatible with your pointers.
The malloc function returns a void * which will quite happily convert implicitly into any other pointer.
Here's a complete program with those fixes:
#include <stdio.h>
#include <stdlib.h>
typedef struct {int size; int id;} DATA;
int comp (const void *a, const void *b) {
return ((DATA *)a)->size - ((DATA *)b)->size;
}
int main (void) {
int i;
DATA *myArray = malloc(10 * sizeof(DATA));
myArray[0].size = 5;
myArray[1].size = 9;
myArray[2].size = 1;
myArray[3].size = 3;
for (i = 4; i < 10; i++)
myArray[i].size = 0;
qsort (myArray, 10, sizeof(DATA), comp);
for (i = 0; i < 10; i++)
printf ("%d ", myArray[i].size);
putchar ('\n');
return 0;
}
The output:
0 0 0 0 0 0 1 3 5 9