I have a dynamically allocated array of structures, 'buff'. Each element is a structure that has a few integer variables and a pointer 'buffer_ptr' which points to another dynamically allocated array of structures. The size of both arrays is given as command line input.
int buffer_size;
int user_num;
struct tuple
{
char userID[5];
char topic[16];
int weight;
};
struct buff_ctrl
{
struct tuple* buffer_ptr;
int in;
int out;
int numItems;
int done;
};
The arrays are created and initialized in main() as follows:
int main(int argc, char* argv[])
{
void *status;
pthread_t mapThd;
if(argc != 4)
{
printf("Input format: ./combiner <buffer_size> <number_of_users> <input_file>\n");
return -1;
}
buffer_size = atoi(argv[1]);
user_num = atoi(argv[2]);
struct buff_ctrl *buff = (struct buff_ctrl*)malloc(user_num * sizeof(struct buff_ctrl));
for(int i=0; i<user_num; i++)
{
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
struct tuple *ptr = (struct tuple*)malloc(buffer_size * sizeof(struct tuple));
curr_buff->buffer_ptr = ptr;//points to another array
curr_buff->in = 8;
curr_buff->out = 4;
curr_buff->numItems = 7;
curr_buff->done = 0;
printf("%p\n",curr_buff);
}
Then, I need to pass the 'buff' pointer as an argument when creating thread using pthread_create:
pthread_create(&mapThd, NULL, mapper, (void*)buff);
pthread_join(mapThd, &status);
free(buff);
/*end of main*/
My function pointer is as follows:
void* mapper(void *buff)
{
struct buff_ctrl* arr = (struct buff_ctrl *)buff;
struct buff_ctrl* temp_ptr;
printf("######################################################\n");
for(int k=0; k<user_num; k++)
{
/*Printing just to check values */
temp_ptr = arr + (k*sizeof(struct buff_ctrl));
printf("buffer ptr = %p\n", temp_ptr->buffer_ptr);
printf("in = %d\n", temp_ptr->in);
printf("out = %d\n", temp_ptr->out);
printf("numItems = %d\n", temp_ptr->numItems);
}
printf("######################################################\n");
pthread_exit((void*)buff);
}
But, when I print the values of 'buffer_ptr' from the created thread (only one), for ODD number of user_num, there is always ONE element of the array 'buff' which gives garbage value after pthread_create statement! When the values are checked in main itself after removing calls to pthread, it runs fine.
This line
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
should be
struct buff_ctrl* curr_buff = buff + i;
buff + i is pointer arithmetic and the compiler already takes the size of the
object pointed to by buff into consideration. By doing i*sizeof(struct buff_ctrl) you are assigning
a pointer that may be after the allocated memory.
As general suggestion:
Don't cast malloc. And instead of using sizeof(<type>), use sizeof *variable, this is more safe, because
it's easier to make mistakes when writing sizeof(<type>).
So:
struct buff_ctrl *buff = malloc(user_num * sizeof *buff);
...
struct tuple *ptr = malloc(buffer_size * sizeof *ptr);
And you don't need to declare a separate pointer, you can do:
for(int i=0; i<user_num; i++)
{
buff[i].buffer_ptr = malloc(buffer_size * sizeof *buff[i].buffer_ptr);
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also you should always check for the return value of malloc. If it returns
NULL, you cannot access that memory.
This is wrong:
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
When you do pointer arithmetic, it operates in units of the size of what the pointer points to, so you don't need to multiply by sizeof. As a result, you're effectively multiplying twice and accessing outside the array bounds.
Just treat buff as an array, rather than dealing with pointers.
for(int i=0; i<user_num; i++)
{
struct tuple *ptr = malloc(buffer_size * sizeof(struct tuple));
buff[i].buffer_ptr = ptr;//points to another array
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also, see Do I cast the result of malloc?
You have a fundamental error.
Pointer arithmetics works by adding the offset in multiples of the pointer type, so adding the offset yourself will not work as you apparently expect it to.
If it was a char * pointer then you would need to add the offset manually, increments would be multiplied by one. But in your case increments by n are multiplied by the size of the pointer base type.
There are times when doing pointer arithmetics with the addition notation makes sense, but most of the time it's much clearer to write index notation instead.
Related
I'm trying to read some float values as an array to a struct member as shown below:
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <stdio.h>
#define MAX_IN 10
typedef struct S_t S_t;
struct S_t {
float *sptr;
uint32_t ns;
};
S_t *getInputS(char *sdfile)
{
FILE *inSFP;
float fvls[MAX_IN];
static S_t inS;
int n;
inSFP = fopen(sdfile, "r");
if (inSFP == NULL) {
printf("\nFailed to open input file...!!!\n");
}
else {
n = 0;
while (fscanf(inSFP, "%f", &fvls[n]) != EOF) {
printf("fvls[%d] = %f\n", n, fvls[n]);
n++;
}
printf("\nScanned all inputs....\n");
inS.ns = (uint32_t) n;
inS.sptr = (float *) malloc(n * sizeof(float));
inS.sptr = fvls;
for(int i = 0; i < n; i++)
printf("inS.sptr[%d] = %f\n", i, inS.sptr[i]);
printf("\nInput read from file %s....\n", sdfile);
fclose(inSFP);
printf("\nClosed file...");
}
return &inS;
}
int main(int argc, char *argv[])
{
S_t *inpS = malloc(sizeof(*inpS));
inpS->sptr = malloc(MAX_IN * sizeof(inpS->sptr));
S_t *outS = malloc(sizeof(*outS));
outS->sptr = malloc(MAX_IN * sizeof(outS->sptr));
static uint32_t n;
char *inFN = argv[1];
char *outFN = argv[2];
inpS = getInputS(inFN);
printf("\nContent from main : \n");
n = inpS->ns;
for(int i = 0; i < n; i++)
printf("%f", *(inpS->sptr + i));
// printf("%f", inpS->sptr[i]);
printf("\nS structure updated (ns = %d)....\n", n);
return 0;
}
This returns the following:
fvls[0] = 0.430000
fvls[1] = 0.563210
fvls[2] = 0.110000
fvls[3] = 1.230000
fvls[4] = -0.034000
Scanned all inputs....
inS.sptr[0] = 0.430000
inS.sptr[1] = 0.563210
inS.sptr[2] = 0.110000
inS.sptr[3] = 1.230000
inS.sptr[4] = -0.034000
Input read from file in.txt....
Closed file...
Content from main :
-0.0000000.0000000.0000000.000000-nan
S structure updated (ns = 5)....
Input values (Original Input):
[0.000000, 0.000000, -0.000000, 0.000000, -0.000000]
The values are indeed read from the input file by the function getInputS() correctly, but on return the member sptr's values are returned incorrectly.
I am using a static variable of type S_t to store the values so that the value is retained. Inspite of that, the values seem to have lost! What am I doing wrong here? How do I fix this?
In this line:
inS.sptr = (float *) malloc(n * sizeof(float));
you cause sptr to point to a malloc'ed region of just the right size for your inputs.
That's good.
But in the very next line:
inS.sptr = fvls;
you throw the malloc'ed pointer away, overwriting it with a pointer to the local fvls array, which is going to disappear when this function returns.
Stated another way: when you store a pointer in a pointer variable, it's just like storing any other value in any other variable. Any time you do something like this:
a = b;
a = c;
you are throwing away the effect of the first assignment, and when you're done, all a is left holding is the value of c. It's no different when a is a pointer variable and b and c are two different pointer values.
Whenever you work with pointers, you have to keep clear in your mind the distinction between the pointer and what the pointer points to. In your getInputS function, you have to worry about both: you have to set the pointer sptr to point to valid storage to contain the values you've read, and you have to set what the pointer points to to be those values. When you say
inS.sptr = (float *) malloc(n * sizeof(float));
you're setting the pointer. But when you say
inS.sptr = fvls;
you're resetting the pointer to something else. But you never get around to setting what the pointer points to (the first, malloc'ed pointer, that is) at all.
And, to be clear, the line
inS.sptr = fvls;
copies the pointer, it does not copy the pointed-to data, which is what you need at this point.
To fix this, either:
Copy data from fvls to sptr (in place of the line inS.sptr = fvls). You can call memcpy, or you can use a loop repeatedly assigning sptr[i] = fvls[i].
Get rid of fvls, initialize sptr to malloc(MAX_IN * sizeof(float));, read directly into sptr, and then at the end, if you want to try to minimize wasted space, call realloc to reallocate sptr down to just big enough for the number of values you actually read.
I need to have a global dynamic array of pointers, in which I will store my structs, beacuse later I will need to iterate through this array to list all the stored information, I also need to be able to read the name, age and job variables from the console, and store them in a person_t in the iterator array.
#include <stdio.h>
#include <stdlib.h>
typedef struct Person
{
char name[30];
int age;
char job[30];
} person_t;
person_t **iterator;
int capacity = 10;
int size = 0;
int main()
{
int i;
*iterator = (person_t *)malloc(capacity * sizeof(person_t));
for (i = 0; i < capacity; ++i)
{
person_t p;
p.age = i;
*iterator[i] = p;
}
return 0;
}
I get no errors/warnings compiling this code (gcc -ansi -pedantic -Wall -Wextra), but when I try to run it, I get a Segmentation fault immediately.
When you do this:
*iterator = (person_t *)malloc(capacity * sizeof(person_t));
You're deferencing iterator, however as a file-scope pointer variable it's initialized to NULL. Attempting to dereference a NULL pointer invokes undefined behavior.
I suspect what you really want is an array of structs, not an array of pointers to structs. That being the case, define iterator as:
person_t *iterator;
Then you allocate memory for it like this:
iterator = malloc(capacity * sizeof(person_t));
Then assign to array elements like this:
iterator[i] = p;
Your stated purpose is to create a "global dynamic array of pointers, in which I will store my structs". The following modification of your code (see comments) will do this:
person_t p[10] = {0};
int main()
{
int i;
// with declaration: person_t **iterator = NULL;,
//following is all that is needed to create an array of pointers:
iterator = malloc(capacity * sizeof(person_t *));//no need to cast return of malloc
for (i = 0; i < capacity; ++i)
{
//person_t p;//moved to scope that will exist outside of main()
p[i].age = i;
iterator[i] = &p[i];//assign the address of the object to the pointer
//iterator[i] is the ith pointer in a collection of
//pointers to be assigned to point to
//instances of struct person_t
}
//Once all fields are populated (to-do), the following will display the results:
for (i = 0; i < capacity; ++i)
{
printf("%d) Name: %s Age: %d Job: %s\n", i, iterator[i]->name,iterator[i]->age,iterator[i]->job);
}
return 0;
}
you are not allocating memory correctly
First you need to allocate memory for a pointer which can store capacity number of address i.e done through iterator = malloc(capacity * sizeof(person_t*)); and then you need to allocate memory for holding each structure element i.e iterator[i] = malloc(sizeof(person_t));
all the malloc'ed memory should be free'd once we are done with it.
Also, have not done the error check for malloc's , that is left as an exercise for you.
int main()
{
int i;
// test data
char *names[] = {"ABC", "DEF"};
char *jobs[] = {"Accountant", "Security"};
int ages[] = {50, 60};
// first allocate memory for iterator , which can hold pointers to store iterator poniters
iterator = malloc(capacity * sizeof(person_t*));
for (i = 0; i < capacity; ++i)
{
// now allocate memory for individual iterator
iterator[i] = malloc(sizeof(person_t));
strcpy(iterator[i]->name,names[i]);
iterator[i]->age = ages[i];
strcpy(iterator[i]->job, jobs[i]);
}
for (i = 0; i < capacity; ++i)
{
printf("name = %s ", iterator[i]->name);
printf("Age = %d ", iterator[i]->age);
printf("Job = %s\n", iterator[i]->job);
}
return 0;
}
I am working on a sqlite-.dll for educational purpose.
I am trying to dynamically add a row in my 2 dimensional array for each time the callback function is called with a new row from the database. (e.g. SELECT * FROM CUSTOMER).
The data stored in this array should then be returned as a C-Interface.
SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
char **a = 0;
/*Some sqlite stuff*/
int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);
return a;
}
With the callback function:
static int callback(void *data, int argc, char **argv, char **azColName)
{
char **old = (char **)data;
int num_rows = sizeof(old) / sizeof(old[0]);
int num_cols = sizeof(old[0]) / sizeof(old[0][0]);
old = (char **)realloc(old, (num_rows + 1) * sizeof(char *));
for (int i = 0; i < (num_rows + 1); i++)
old[i] = (char *)realloc(old[i], argc * sizeof(char *));
/*I am trying to create a 2 dim array that looks like a table,
so the column names are in the first row,
then the data from the table is stored in each row*/
for (int i = 0; i < argc; i++)
{
if (num_rows == 1)
old[0][i] = *azColName[i];
old[num_rows][i] = *argv[i];
}
data = old;
return 0;
}
When inserting data to the database, everything works fine. But when I try to retrieve data, I get read access violation.
Now my question, am I on the right way with my approach or do I miss some important requirements for my intention?
In your sql_execQuery(), you declare a as a char **, and you pass its address, &a, as the fourth argument of sqlite3_exec(). That argument therefore has type char ***, and it points to a location somewhere in the program's stack. There's nothing inherently wrong with that.
But then we get to callback(), which has serious problems, principal among them:
It treats the data pointer as if it were of type char **, instead of the correct type, char ***. If that were your only problem, you could fix it like this:
char **old = *(char ***)data;
// ...
*(char ***)data = old;
It tries to compute the dimensions of the allocated space via the sizeof operator, as would be reasonable if old were, in fact, a 2D array, but it is not an array at all. It is a pointer to pointer to char, so sizeof(old) is the size of a pointer (to pointer to char), sizeof(old[0]) is the size of a pointer (to char) and sizeof(old[0][0]) is the size of a char. This does not tell you anything about how much space has been allocated.
After allocating memory for old, it dereferences the parts of the allocated memory without initializing them, by passing them to realloc(). Generally, all but one of these will have been initialized, but the one uninitialized one causes realloc() to exhibit undefined behavior.
You fail to check for allocation errors.
It looks like you need a more complex data structure to be passed through to your callback, so that you can track the allocated dimensions. Something like this, for example:
struct mytable {
char **data;
size_t dim;
};
SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
struct mytable a = { NULL, 0 };
// ...
int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);
return a.data;
}
static int callback(void *data, int argc, char **argv, char **azColName)
{
struct mytable *old = data;
char **temp;
old->dim++;
temp = realloc(old->data, old->dim * sizeof(*old->data));
if (temp) {
old->data = temp;
old->data[old->dim - 1] = NULL;
} else {
// handle allocation error ...
}
for (int i = 0; i < old->dim; i++) {
char *temp2 = realloc(old->data[i], argc * sizeof(*old->data[i]));
if (temp2) {
old->data[i] = temp2;
old->data[i][argc - 1] = NULL;
} else {
// handle allocation error ...
}
}
// ... other stuff ...
// no need for anything like data = old
return 0;
}
Suppose I have array of chars:
char buffer[1024];
The array in fact contains chain of structures in sequence.
struct MyStruct {
char name[4];
int num1;
int num2;
}
I want to loop through the array:
MyStruct *p;
for(int i = 0;i < sizeof(buffer);i += sizeof(MyStruct))
{
// how can I point p to some place in buffer here?
}
I want to point p to start of buffer, the to buffer + 12 etc.
One issue to consider is that the char buffer might not be properly aligned for a struct (and, in this case, its int members num1 and num2). Depending on the platform and implementation, a 4-byte, 8-byte or 16-byte alignment might be required. For that reason, one alternative is to declare the buffer in terms of MyStruct initially and then access it via a char pointer:
MyStruct buffer[1024 / sizeof(MyStruct)];
char * cp = (char *) buffer;
// fill the buffer via cp
for (size_t i = 0; i < sizeof(buffer); ++i)
{
// do stuff with buffer[i]
}
If that approach is not possible, the buffer needs to be copied to another buffer with safe alignment; For example:
size_t n = sizeof(buffer) / sizeof(MyStruct);
MyStruct * p = (MyStruct *) malloc(n * sizeof(MyStruct));
if (!p) { exit(EXIT_FAILURE); }
memcpy(p, buffer, n * sizeof(MyStruct)); // copy buffer to p
for (size_t i = 0; i < n; ++i)
{
// do stuff with p[i]
}
first note that you are assuming that this will work. That there is no padding between the elements of the struct. Having said that do this:
MyStruct *s = (MyStruct*)(buffer + i)
You let p point to the first struct in the buffer, then increment it on each iteration:
MyStruct *p= (struct MyStruct *) buffer;
for(int i = 0; i < sizeof(buffer); i += sizeof(MyStruct), p++)
{
// your code
}
...and yes, this assumes the structs are contiguous in memory, with no padding in between.
My code uses two structures, block and layout (which is a collection of an arbitrary number of blocks).
struct block{
char type;
unsigned short int loc;
unsigned short int size[2];
};
struct layout{
unsigned short int no;
struct block *blocks;
short int **moves;
};
I am using this function to quickly initialize (and partly fill) the structure layout, based a set of blocks:
struct layout init_layout(int block_no, struct block *blocks){
struct layout new_layout;
int i, j;
new_layout.no = (unsigned short int)block_no;
// the following two lines cause an memory corruption error
new_layout.blocks = (struct block *)malloc(block_no);
new_layout.moves = (short int **)malloc(block_no);
for(i = 0; i < block_no; i++){
new_layout.blocks[i] = blocks[i];
new_layout.moves[i] = (short int *)malloc(2);
for(j = 0; j < 2; j++)
new_layout.moves[i][j] = 0;
}
return new_layout;
}
So far, I do not see, that there is something wrong with it. However, when I call function like this
int main(int argc, char** argv){
// just some arbitrary values for 10 blocks
int size[2] = {2, 2};
struct block *blocks = (struct block *)malloc(10);
for(length = 0; length < 10; length++){
blocks[length] = init_block('R', 1, size);
}
struct layout puzzle;
puzzle = init_layout(10, blocks);
return 0;
}
I end up with an memory corruption error, as marked by the comment in init_layout().
What do I miss in my implementation?
When you are allocating memory for anything, you need to analyze, closely -- "What is it that I'm allocating memory for?"
Below, you incorrectly assume a cast of an arbitrary number block_no will adequately size the memory needed for both new_layout.blocks and new_layout.moves -- it won't:
new_layout.blocks = (struct block *)malloc(block_no);
new_layout.moves = (short int **)malloc(block_no);
What you are allocating for new_layout.blocks is actually space for struct block *blocks; (a pointer-to-struct-block), while you can malloc (block_no * sizeof (struct block)); to allocate space for block_no struct block, it is far better to allocate based upon what you are creating (i.e. space for an array new_layout.blocks (again a pointer-to-struct-block) which needs block_no * sizeof *new_layout.blocks bytes of memory to hold block_no of type struct block, e.g.:
new_layout.blocks = malloc(sizeof *new_layout.blocks * block_no);
new_layout.moves = malloc(sizeof *new_layout.moves * block_no);
(simply dereferencing the object you are allocating an array of, will accurate allow you to use sizeof to get the object (element) size for the array. (e.g. sizeof *new_layout.blocks) which you multiply by how many you need (e.g. sizeof *new_layout.blocks * block_no)
The same applies to:
new_layout.moves[i] = malloc(**new_layout.moves * 2);
(note: here you are allocating for 2 shorts, so you will need to dereference you pointer-to-pointer-to-short twice to be allocating for sizeof (short))
See Also: Do I cast the result of malloc? for thorough explanation.
For starters, this
new_layout.blocks = (struct block *)malloc(block_no);
should be
new_layout.blocks = malloc(block_no * sizeof *new_layout.blocks);
For the moves this is a bit more complicated.
Assuming short int **moves; should reference a certain number of int[2] the declaration is not optimal and better should be:
short int (*moves)[2]; /* Define a pointer to
an array with two elements of type short int. */
And allocation then should look like this:
new_layout.moves = malloc(block_no * sizeof *new_layout.moves);
Finally initialisation goes like this:
for(i = 0; i < block_no; i++){
new_layout.blocks[i] = blocks[i];
for(j = 0; j < sizeof new_layout.moves[0]/sizeof new_layout.moves[0][0]; j++)
new_layout.moves[i][j] = 0;
}
You might have noticed:
No memory allocation in the loop any more.
The magic number 2 only appears once.
:-)