Eclipse terminating without message during assignment of 2D-Array element - c

I'm experiencing odd behavior in Eclipse / C. I have the following type declared in, lets say, a.h.
typedef double sig_type[3];
and the following in, lets say, b.c
typedef struct filter_kind {
. . .
sig_type * fil_buff; //The buffer for all values
. . .
} filter_kind;
int init_filter(filter_kind * filter, const sig_type init_data[],
const int data_len) {
if (filter->data_buff_len != data_len) {
return -1
}
int i;
int j;
for (i = 0; i < filter->data_buff_len; i++) {
for (j = 0; j < OUT_NUM; j++) {
(filter->fil_buff)[i][j] = init_data[i][j]; //prog exits on this line.
}
}
filt_coeffs(filter);
return 0;
}
I have a specified function to return a pointer to a malloced filter_kind structure, which mallocs fil_buff. When I use this creation function, and pass the newly created filter_kind pointer to init_filter, the function unexpectedly exits when assigning to (filter->fil_buff)[][] -- with almost no note other than "gdb" in the Debug view.
I've dropped in some probe variables, and viewed them during debug, and nothing seems abnormal up until this point. I can read from the array fine, just cannot assign. Am I doing something wrong here?
And lastly, here is the constructor function with corresponding allocation functions.
filter_kind * create_filter(const double f_lo, const double f_hi,
const double samp_r, win_type window_t, fil_type filter_t,
const int buff_len) {
filter_kind * filter;
sig_type * fil_buff;
int err = 0;
/* allocate filter struct */
filter = (filter_kind *) malloc(sizeof(filter_kind));
err = (filter != NULL ) ? 0 : -1;
if (err == -1) {
return NULL ;
}
memset(filter, 0, sizeof(filter_kind));
/* allocate filter data members */
err = alloc_buffs(win_coeffs, fil_coeffs, fil_buff, buff_len);
if (err == -1) {
return NULL ;
}
//assign other structure values...
filter->fil_buff = fil_buff;
return filter;
}
static int alloc_buffs(double * win_coeffs, double * fil_coeffs,
sig_type * fil_buff, const int buff_len) {
int err = 0;
//allocate other buffers...
err = alloc_st_buff(fil_buff, buff_len);
if (err == -1) {
return -1;
}
return 0;
}
static int alloc_st_buff(sig_type * st_buff, const int buff_len) {
const int num_bytes = sizeof(sig_type) * buff_len;
st_buff = (sig_type *) malloc(num_bytes);
const int err = (st_buff != NULL ) ? 0 : -1;
if (err == -1) {
return -1;
}
memset(st_buff, 0, num_bytes);
return 0;
}
and for what it's worth, designed to be used as follows
filter_kind * filter;
filter = create_filter(...);
/* Load data into array of sig_type, i.e. sig_type arr[40] */
init_filter(filter, arr, 40);
/* more code... */

Ok problem is with allocating buffers (calling allocating function):
sig_type * fil_buff;
err = alloc_buffs(win_coeffs, fil_coeffs, fil_buff, buff_len);
filter->fil_buff = fil_buff;
So what is happening here:
Create pointer to a table called fil_buff,
call function alloc_buffs with copies of pointers to fil_buff etc.,
assign not changed fil_buff to a structure.
Every time function takes argument it makes a copy of it. So when you passed a pointer, then function made a copy of this pointer (and it was operating on a copy of the pointer), thus original pointer (before function call) is not changed. You should pass pointer to the pointer you want to operate on. The way it could be done is:
err = alloc_buffs(win_coeffs, fil_coeffs, &fil_buff, buff_len);
^^^^^^^^^
then your fil_buff can really be changed, but you have to adjust your function to take proper arguments and to properly operate on them. I guess the same mistake has been made with other buffers.

Related

Creating an array of structs by adding dynamically some struct-elements

I've been struggling with C pointers for hours now. I'm trying to create a C program which manages flights. A flight contains the following:
flight-number, from, to, date, price
OS772,Vienna,New York,15.12.2018,638.00
Therefore, I'm reading a textfile of this given structure. On every line read, I need to create another struct and add it to my array or "list" of structs.
The struct looks like:
typedef struct flights {
char *flnum;
char *from;
char *to;
char *date;
float price;
struct person *fPerson;
}flights;
My problem: Inside the function, the array of structs is created properly. But back in the main-function, the pointer to the array called 'flights **flight_list' is still NULL.
Here is the code (only the necessary parts):
int main(void) {
flights **flight_list = NULL;
int numFlights = 0;
if (!(numFlights = load_flights(flight_list)))
return EXIT_FAILURE;
/* value of flight_list = 0x0000 -> unchanged! */
/* ... */
Function short load_flights(flights **flight_list):
short load_flights(flights **flight_list) {
FILE *fp = NULL;
char file_buffer[256] = {};
int i = 0;
if (fp = fopen("flights.txt", "r")) {
/* create array of structs */
flight_list = (flights **)calloc(1, sizeof(int));
while (!feof(fp)) {
/* read current line of flight from textfile */
fgets(file_buffer, sizeof(file_buffer), fp);
/* create a new struct and add it to the array */
if ((flight_list[i] = (flights *)calloc(1, sizeof(flights))) != NULL) {
/* create every variable of the struct */
flight_list[i]->flnum = (char *)calloc(1, strlen(ptr)+1);
/* ... */
}
i++;
}
}
else return 0;
/* values of the struct-array are properly set; look in attached picture */
return i;
}
This image was taken while debugging the array-creation process before return i;:
And here outside the function; inside main:
So, why is my array of structs gone in the main-function?
You need to pass the address of a pointer variable to load_flights. Then load_flights needs to indirect through the variable to modify the caller's variable.
To handle the dynamic size of the input, you need to use realloc() each time through the loop to grow the array.
int main(void) {
flights **flight_list = NULL;
int numFlights = 0;
if (!(numFlights = load_flights(&flight_list)))
return EXIT_FAILURE;
/* ... */
}
short load_flights(flights ***flight_list) {
FILE *fp = NULL;
char file_buffer[256] = {};
int i = 0;
if (fp = fopen("flights.txt", "r")) {
/* create array of structs */
flight_list **temp_flight_list = NULL;
/* read current line of flight from textfile */
while (fgets(file_buffer, sizeof(file_buffer), fp)) {
// Grow the flight list array
flights **new_flight_list = realloc(*flight_list, (i+1) * sizeof(flight_list *));
if (new_flight_list == NULL) { // allocation failed, throw everything away
for (int j = 0; j < i-1; j++) {
free(temp_flight_list[i]->flnum);
free(temp_flight_list[i]->from);
/* ... */
free(temp_flight_list[i]);
}
free(temp_flight_list);
return 0;
}
temp_flight_list = new_flight_list;
/* create a new struct and add it to the array */
if ((temp_flight_list[i] = calloc(1, sizeof(flights))) != NULL) {
// Parse the buffer ...
/* create every variable of the struct */
temp_flight_list[i]->flnum = calloc(1, strlen(ptr)+1);
/* ... */
} else { // allocation failed, throw everything away
for (int j = 0; j < i-1; j++) {
free(temp_flight_list[i]->flnum);
free(temp_flight_list[i]->from);
/* ... */
free(temp_flight_list[i]);
}
free(temp_flight_list);
return 0;
}
i++;
}
// Store new flight list in caller's variable
*flight_list = temp_flight_list;
return i;
}
else return 0;
}
See also
Do I cast the result of malloc?
and
Why is “while (!feof(file))” always wrong?

Creating struct objects and puttin them into an array

I'm trying to solve a problem I'm having with a function that will create a new struct objects and then put it in an dynamic array. I have tried multiple variations but i keep running into various problems. This is what I'm working with right now, but I'm getting a memory access problem.
typedef struct {
int keynr;
int access;
time_t lastused;
} keycard;
void keyCreate(keycard *cardList, int keyid) {
cardList[keyid].keynr = keyid + 100;
cardList[keyid].access = 1;
cardList[keyid].lastused = 0.0;
}
int main () {
keycard *cardList = 0;
cardList = malloc(sizeof(keycard) * 1);
keyCreate(&cardList, 0);
printf("%d", cardList[0].access);
This code gives me: Exception thrown: read access violation.
cardList was 0x64.
I've been reading alot about pointers and memmory allocation but obviously i am missing something..
You if you want to duynamically add new cards to the array, you need to wrap it in another data structure:
typedef struct
{
int keynr;
int access;
time_t lastused;
} keycard;
typedef struct
{
keycard *keyarray;
size_t size;
}keystorage;
int keyCreate(keystorage *cardList, size_t keyid)
{
if (cardList -> keyarray == NULL || keyid + 1 > cardList -> size)
{
keycard *new = realloc(cardList -> keyarray, sizeof(*(cardList -> keyarray)) * (keyid + 1));
if(!new) return -1; //error
cardList -> keyarray = new;
cardList -> size = keyid + 1;
}
cardList -> keyarray[keyid].keynr = keyid + 100;
cardList -> keyarray[keyid].access = 1;
cardList -> keyarray[keyid].lastused = 0.0;
return 0; //OK
}
int main (void) {
keycard key;
keystorage cards = {NULL, 0};
keyCreate(&cards, 500);
printf("%d", cards.keyarray[500].access);
return 0;
}
You are passing the incorrect type to keyCreate. This function expects a pointer to keycard, but you are passing it a double pointer instead. The & means "take the address of", which turns cardList into a keyCard** type. Instead, consider the following:
void keyCreate(keycard *cardList, int keyid) {
cardList[keyid].keynr = keyid + 100;
cardList[keyid].access = 1;
cardList[keyid].lastused = 0; // time_t is most likely a signed integer
}
int main (void) {
keycard *cardList = malloc(sizeof(keycard) * 1);
// always check if malloc succeeds, and if it does not, handle the error somehow
if (cardList == NULL)
{
fprintf(stderr, "Insufficient mem\n");
return -1;
}
keyCreate(cardList, 0);
printf("%d\n", cardList[0].access); // the \n will flush the output and
// put each item on its own line
// cleanup when you're done, but the OS will do this for you when the
// process exits also
free(keyCreate);
return 0;
}
Also, time_t is most likely a signed integer (What is ultimately a time_t typedef to?), so assigning it to 0.0 is probably not right, but you'll need to check what it typedefs to on your system.
Finally, I assume this is just an MCVE, but I'd advise against mallocing in this case. The 2 primary reasons to malloc are when you don't know how much data you'll need until runtime, or you need "a lot" of data. Neither of those are true in this case. Just from what you've presented, I'd probably do the following:
#define NUM_KEY_CARDS 1
void keyCreate(keycard *cardList, int keyid) {
cardList[keyid].keynr = keyid + 100;
cardList[keyid].access = 1;
cardList[keyid].lastused = 0; // time_t is most likely a signed integer
}
int main (void) {
keycard cardList[NUM_KEY_CARDS];
for (int keyid=0; keyid<NUM_KEY_CARDS; keyid++)
{
keyCreate(cardList+keyid, keyid);
// or keyCreate(&(cardList[keyid]), keyid);
printf("%d\n", cardList[keyid].access);
}
return 0;
}

c++ function with static variable returning next value in array

Create a function with a static variable that is a pointer (with a default argument of zero). When the caller provides a value for this argument it is used to point at the beginning of an array of int. If you call the function with a zero argument (using the default argument), the function returns the next value in the array, until it sees a “-1” value in the array (to act as an end-of-array (indicator). Exercise this function in main( ).
Here is what I have :
int pr(int *p = 0) {
static int* po =0 ;
if (p) {
po = p;
return *po;
}
else {
return -1;
}
if (*p == -1) {
return -1;
}
return *po++;
}
int ar[] = {2,5,1,2,6,-1};
int main() {
pr(ar);
int pl;
pl = pr();
while (pl != -1) {
cout << pl << endl;
pl = pr();
}
}
When I start it, nothing gets printed and I dont know why. Any help ?
You will need to keep the next array index around, too:
int f(int* a = NULL) {
static int* arr = NULL; // internal state ...
static int idx = 0; // ...in these two vars
// Reset the internal state if a new array is given
if (a != NULL) {
arr = a;
idx = 0;
}
// #1
if (arr == NULL || arr[idx] == -1) { return -1; }
return arr[idx++];
}
I made some assumptions about the parts you didn't specify in your question on the line marked #1. If no pointer has yet been provided, or if the array end has previously been reached, we just return -1 each time.

Tricky Heap corruption Bug?

EDIT: What I thought was a bug-correction was nothing but a random fix. I was forgetting to free up heap memory correctly. See the actual code and explanation at the bottom (I'm not sure if I should have edited the whole question).
I haved fixed a bug, but do not understand what it's causing it.
If I use a helper pointer to access the element of a list in the heap, and modify its contents, everything's fine. However, if I directly modify the contents of the element using a function that returns that pointer, then this data gets corrupted at a later stage when allocating more memory.
The error only appears when the code is run in a loop, on the 6th cycle.
Code does not work
// numEvents gets corrupted after some cycles
lstEvent_NewList(&lstEvent, 1, &err); // creates a list of typeEvent in heap
//...
lstEvent_FirstNode(&lstEvent)->numEvents = events; // access first element of list directly
//...
typeCommand * p = 0;
p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
lstField_NewList(&p->lstFields, 5, &err); // THIS LINE CAUSES CORRUPTION IN numEvents
Code does work
typeEvent * pEvent; // use an auxiliar to iterate through the list
lstEvent_NewList(&lstEvent, 1, &err);
//...
pEvent = lstEvent_FirstNode(&lstEvent);
pEvent->numEvents = events;
//...
typeCommand * p = 0;
p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
lstField_NewList(&p->lstFields, 5, &err); // all is good
So, basically if I use an auxiliar to get the first element of the list nothing happens. However, if I use the function to directly access the first element, it breaks later on in the program.
Structure and function definitions:
typeEvent * lstEvent_FirstNode (LSTEvent *lst)
{
return lst->ls;
}
void lstEvent_NewList (LSTEvent * lst, uint16_t size, uint8_t * err)
{
typeEvent* ret = 0;
ret = (typeEvent*)malloc(sizeof(typeEvent)*size);
if (ret == 0)
{
*err = E_RUN_OUT_OF_MEM;
lst->cn = 0;
return;
}
*err = 0;
lst->ls = ret;
lst->cn = size;
}
void lstField_NewList (LSTField * lst, uint16_t size, uint8_t * err)
{
typeField* ret = 0;
ret = (typeField*)malloc(sizeof(typeField)*size);
if (ret == 0)
{
*err = E_RUN_OUT_OF_MEM;
lst->cn = 0;
return;
}
*err = 0;
lst->ls = ret;
lst->cn = size;
}
void lstEvent_ClearList (LSTEvent * lst)
{
free(lst->ls);
lst->ls = 0;
lst->cn = 0;
}
void lstField_ClearList (LSTField * lst)
{
free(lst->ls);
lst->ls = 0;
lst->cn = 0;
}
struct DM_Field{
__packed uint8_t value;
};
typedef struct DM_Field typeField;
typedef struct LSTField {
__packed uint16_t cn; // Count, number of elements in array
uint8_t * ls; // Array
} LSTField;
struct DM_Command{
// some data
LSTField lstFields;
};
typedef struct DM_Command typeCommand;
Platform: STM32L1XX.
EDIT: This code resembles closer the reality.
Code does not work
typeCommand * p = 0;
for (uint16_t i=0; i<1000; i++)
{
// numEvents gets corrupted after some cycles
lstEvent_NewList(&lstEvent, 1, &err); // creates a list of typeEvent in heap
//...
lstEvent_FirstNode(&lstEvent)->numEvents = events; // access first element of list directly
//...
p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
lstField_NewList(&p->lstFields, 5, &err); // THIS LINE (was thought to be causing) CORRUPTION IN numEvents
//...
lstEvent_ClearList(&lstEvent);
lstField_ClearList(&p->lstFields);
p = 0;
}
Code does work
typeCommand * p = 0;
typeEvent * pEvent; // use an auxiliar to iterate through the list
for (uint16_t i=0; i<1000; i++)
{
lstEvent_NewList(&lstEvent, 1, &err);
//...
pEvent = lstEvent_FirstNode(&lstEvent);
pEvent->numEvents = events;
//...
p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
lstField_NewList(&p->lstFields, 5, &err); // all is good
//...
lstEvent_ClearList(&lstEvent);
lstField_ClearList(&p->lstFields);
free(p); // freeing properly now
p = 0;
}

How could I know an Uncertain type parameters' size

const static int VECTOR_BASIC_LENGTH = 20;
struct m_vector
{
void* my_vector;
size_t my_capacity;
size_t my_head;
};
typedef struct m_vector Vector;
Vector creat_Vector(size_t size,void *judge)
{
Vector _vector;
size = size?size:VECTOR_BASIC_LENGTH;
_vector.my_capacity = size;
_vector.my_head = 0;
//How I write the following two lines
_vector.my_vector = malloc(sizeof(*judge) * size);
return _vector;
}
The type of judge is uncertain,so I pass a void pointer as a parameters.I need the size of *judge to allocate memory to _vector.my_vector,for example if I use:
int *a;
creat_Vector(5,a);
I want the following line:
_vector.my_vector = malloc(sizeof(*judge)*size);
is equal to:
_vector.my_vector = malloc(sizeof(*a)*5);
How could I achieve this function.Using pure C
There is a forbidden thing done in your code.
You statically (at compile time) allocate/declare a local _vector of type Vector in your function creat_Vector. Then you return this object to the outside world. However, when you are exiting your function, all local data is dead. So, you should absolutely rethink this.
One suggestion would be:
int init_Vector(Vector* _vect, size_t size, unsigned int ptr_size)
{
size = size?size:VECTOR_BASIC_LENGTH;
_vect->my_capacity = size;
_vect->my_head = 0;
_vect->my_vector = malloc(size*ptr_size);
if (_vect->my_vector) {
return 0;
}
return 1;
}
Then:
Vector _vector;
char *a;
if (init_Vector(&_vector, 5, sizeof(char)) == 0) {
printf("Success!\n");
}
else {
printf("Failure!\n");
/* treat appropriately (return error code/exit) */
}
/* do whatever with a (if needed) and _vector*/

Resources