Heyo,
I have problem allocating memory for my "database"
i have this struct
typedef struct TPrvek {
struct TPrvek *parent1;
struct TPrvek *parent2;
int id;//key
char *name;//value
} TPrvek;
typedef struct Database {
int size;
struct TPrvek **TField;
} DATABASE;
and I am initializing like this :
void init(DATABASE *db) {
DATABASE *newDb = (DATABASE *) malloc(sizeof(DATABASE));
newDb->size = 1000;//initial capacity
newDb->TField = (TPrvek **) calloc(newDb->size, sizeof(TPrvek *));
for (int i = 0; i < db->size; i++) {
newDb->TField[i] = NULL;
}
*db = *newDb;
}
But when i try to insert smth to it, im writing out of allocated memmory and I don't know how to repair it nor what is even wrong
snipet of insertion:
int addPerson(DATABASE *db,
int id,
const char *name,
int id1,
int id2) {
//some checks to make sure ids are in bounds and field for new person is empty
TPrvek *clovek = (TPrvek *) malloc(sizeof(TPrvek));
clovek->name = (char *) malloc(sizeof(name) + 1);
strcpy(clovek->name, name);
clovek->id = id;
//clovek->parent1 = (TPrvek *) malloc(sizeof(TPrvek));
//clovek->parent2 = (TPrvek *) malloc(sizeof(TPrvek));I was desperate, this is wrong I think
clovek->parent1 = db->TField[id1];
clovek->parent2 = db->TField[id2];
db->TField[id] = clovek;
//returns 1 if success
}
and in the main I have simple asserts to check functionality like :
int main(int argc,
char *argv[]) {
DATABASE a;
init(&a);
assert (addPerson(&a, 1, "John", 0, 0) == 1);
assert (addPerson(&a, 2, "Caroline", 0, 0) == 1);
...}
Any ideas?
I'm pretty new to c and memory allocating in general, so I would be glad for every bit of help :)
This line is the problem (at least one I see straight away):
clovek->name = (char *) malloc(sizeof(name) + 1);
Type of name is char *, and sizeof(char *) is size of pointer - always 8.
What you need instead is the length of string, i.e:
clovek->name = (char *) malloc(strlen(name) + 1);
Related
I am trying to create a dynamic array of Clients, but i am not succeding. This is my code. When i run this code the output is
3
� H
3
4332
3
8939
I think it's printing memory stuff, however i don't know why. I put my code down here
int client_counter = 0;
typedef struct client
{
char *pid;
char *message;
}Client;
void store (Client * client_array, char *buf)
{
Client c;
c.pid = strdup (strtok (buf, ":"));
c.message = strdup (strtok (NULL, "\0"));
client_array[client_counter++] = c;
}
int main () {
Client* client_array = malloc (sizeof (struct client));
char buf1[50] = { "1245:message" };
store (client_array, buf1);
char buf2[50] = { "4332:message" };
store (client_array, buf2);
char buf3[50] = { "8939:message" };
store (client_array, buf3);
for (int i = 0; i < client_counter; i++)
{
printf ("%d\n", client_counter);
printf ("%s\n", client_array[i].pid);
}
return 0;
}
I already tried do use this:
client_array = realloc(client_array, sizeof(struct client) * (client_counter + 1));
in store function right after this line.
client_array[client_counter++] = c;
But it's not working too.
You need to allocate extra memory if there's not enough space. Right now, you allocate enough for one, but you try to access three.
Don't forget to return the pointer of the new memory block back to main! In the following, this is done by passing a pointer to the caller's pointer. store modifies the caller's pointer via the passed pointer.
// Sets errno and returns 0 on error.
int store(Client ** client_array_ptr, char *buf) {
Client* new_client_array = realloc(*client_array_ptr, sizeof(Client) * (client_counter + 1));
if (!new_client_array)
return 0;
*client_array_ptr = new_client_array;
// ...
new_client_array[client_counter++] = c;
return 1;
}
int main() {
Client* client_array = NULL;
// ...
if (!store(&client_array, buf1)) {
perror("malloc");
exit(1);
}
// ...
if (!store(&client_array, buf2)) {
perror("malloc");
exit(1);
}
// ...
free(client_array);
return 0;
}
The original code does out-of-range access because it is trying to store multiple data in a buffer which is allocated for only one element.
To use realloc(), you have to note that arguments of functions in C are copies of what are passed. Modifying arguments inside callee function do not affect what is passed in caller. You should pass pointers to what should be modified to have functions modify caller's local things.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int client_counter = 0;
typedef struct client
{
char *pid;
char *message;
}Client;
void store (Client ** client_array, char *buf)
{
Client c;
c.pid = strdup (strtok (buf, ":"));
c.message = strdup (strtok (NULL, "\0"));
*client_array = realloc(*client_array, sizeof(struct client) * (client_counter + 1));
(*client_array)[client_counter++] = c;
}
int main () {
Client* client_array = malloc (sizeof (struct client));
char buf1[50] = { "1245:message" };
store (&client_array, buf1);
char buf2[50] = { "4332:message" };
store (&client_array, buf2);
char buf3[50] = { "8939:message" };
store (&client_array, buf3);
for (int i = 0; i < client_counter; i++)
{
printf ("%d\n", client_counter);
printf ("%s\n", client_array[i].pid);
}
return 0;
}
I would do it a bit different way.
typedef struct
{
char *pid;
char *message;
}client_TypeDef;
typedef struct
{
size_t size;
client_TypeDef clients[];
}clients_TypeDef;
clients_TypeDef *add(clients_TypeDef *clients, const char *pid, const char *message)
{
size_t newsize = clients ? clients -> size + 1 : 1;
client_TypeDef client = {.pid = strdup(pid), .message = strdup(message)};
if(client.pid && client.message)
{
clients = realloc(clients, sizeof(*clients) + newsize * sizeof(clients -> clients[0]));
if(clients)
{
clients -> size = newsize;
clients -> clients[newsize - 1] = client;
}
}
else
{
free(client.pid);
free(client.message);
clients = NULL;
}
return clients;
}
I'm trying to create a string matrix in C to stores the results of a sql callback. For some reason, it always crashes on the 12th reallocation of "data" even though the memory address of data is the same.
Thanks.
int row_index;
static int db_select_cb(void *p_data ,int argc, char **argv, char **azColName){
char ***data = (char ***)p_data;
data = (char ***)realloc(data,sizeof(char **)*(row_index+1));
data[row_index] = (char **)malloc(sizeof(char *)*(argc));
for(int col_index = 0;col_index < argc;col_index++){
data[row_index][col_index] = (char *)malloc(sizeof(char)*(strlen(argv[col_index])+1));
strcpy(data[row_index][col_index],argv[col_index]);
}
row_index++;
return 0;
}
char ***db_select(sqlite3 *conn,unsigned char *zSQL){
row_index = 0;
char ***data = (char ***)malloc(sizeof(char ***)*(row_index+1));
char *err = 0;
int cerr = sqlite3_exec(conn,zSQL,db_select_cb,(void*)data,&err);
if(cerr){
printf(":: SQL ERROR IN \"db_select\" || %s ||\n", err);
sqlite3_free(err);
return 0;
}
return data;
}
Thanks for your help guys. The problem was that I needed to pass a reference to the matrix to the callback as realloc was modifying data. Here's what ended up working.
int row_index;
static int db_select_cb(void *p_data ,int argc, char **argv, char **azColName){
char ****data = (char ****)p_data;
*data = realloc(*data,sizeof(char **)*(row_index+1));
(*data)[row_index] = malloc(sizeof(char *)*(argc));
for(int col_index = 0;col_index < argc;col_index++){
(*data)[row_index][col_index] = malloc(sizeof(char)*(strlen(argv[col_index])+1));
strcpy((*data)[row_index][col_index],argv[col_index]);
}
row_index++;
return 0;
}
char ***db_select(sqlite3 *conn,unsigned char *zSQL){
row_index = 0;
char ***data = malloc(sizeof(char **)*(row_index+1));
char *err = 0;
int cerr = sqlite3_exec(conn,zSQL,db_select_cb,(void*)&data,&err);
if(cerr){
printf(":: SQL ERROR IN \"db_select\" || %s ||\n", err);
sqlite3_free(err);
return 0;
}
return data;
}
Here is an updated solution using structs which as Groo pointed out is the only way to keep track of the row and columns sizes.
typedef struct{
char ***data;
int row_size;
int *col_size;
}Table;
static int db_select_cb(void *p_table ,int argc, char **argv, char **azColName){
Table **table = (Table **)p_table;
(*table)->data = realloc((*table)->data,sizeof(char **)*((*table)->row_size+1));
(*table)->data[(*table)->row_size] = malloc(sizeof(char *)*(argc));
(*table)->col_size = realloc((*table)->col_size,sizeof(int)*((*table)->row_size+1));
int col_index;
for(col_index = 0;col_index < argc;col_index++){
(*table)->data[(*table)->row_size][col_index] = malloc(sizeof(char)*(strlen(argv[col_index])+1));
strcpy((*table)->data[(*table)->row_size][col_index],argv[col_index]);
}
(*table)->col_size[(*table)->row_size] = col_index;
(*table)->row_size++;
return 0;
}
Table *db_select(sqlite3 *conn,unsigned char *zSQL){
Table *table = malloc(sizeof(Table));
table->row_size = 0;
table->data = NULL;
table->col_size = NULL;
char *err = 0;
int cerr = sqlite3_exec(conn,zSQL,db_select_cb,(void*)&table,&err);
if(cerr){
printf(":: SQL ERROR IN \"db_select\" || %s ||\n", err);
sqlite3_free(err);
return 0;
}
return table;
}
Your life would be much easier if you would create a couple of sanely named structs and some tiny helper functions.
First of all, your db_select function returns an allocated data, but sets a global variable row_index. Number of columns is lost forever. But this already indicates that you need a struct - you want to pack all information that this function needs to give you into a single "coherent" block.
So, you might say a row is a bunch of columns:
typedef struct {
char *cols;
int cols_count;
} Row;
And a table is a bunch of rows:
typedef struct {
Row * rows;
int rows_count;
} Table;
And now you handle allocation and housekeeping separately (note: I am writing this in the browser, haven't even checked if it will compile):
// allocates a new table
Table * Table_create(void) {
Table * table = calloc(1, sizeof *table);
return table;
}
// creates a new child row in the table, with the specified number of cols
Row * Row_create(Table *table, int numCols) {
table = realloc(table, table->rows_count * sizeof *table);
table->rows_count++;
Row * newRow = &table->rows[table->rows_count - 1];
newRow->cols = calloc(numCols * sizeof *newRow->cols);
newRow->cols_count = numCols;
return newRow;
}
Sqlite functionality now looks quite simpler:
// this obviously allocates a new table, so somebody will have to
// free it at some point
Table * table_fetch_from_db(sqlite3 * conn, unsigned char * sql) {
Table * table = Table_create();
if (sqlite3_exec(conn, sql, load_single_row, table, NULL)) {
// handle error
}
return table;
}
int load_single_row(void *args, int numCols, char **cols, char **colNames) {
// we passed a Table* as args
Table * table = (Table*)args;
// allocate a new row inside table
Row * row = Row_create(table, numCols);
for (int i = 0; i < numCols; i++) {
int single_col_len = strlen(cols[col_index]);
row->cols[i] = malloc(single_col_len * sizeof *row->cols[i]);
strcpy(row->cols[i], cols[i]);
}
return 0;
}
If you're using C99, this code might be slightly simplified using flexible array members, because you don't need to allocate the struct and the inner array separately.
Note that I haven't tested any of this, it lacks functions for freeing tables, and possibly won't fix your actual issue. :)
I have structs:
typedef struct accont
{
char **tel;//list of tel
char **email;//list of emails
}acc;
and
typedef struct _strcol
{
int count; //total of accounts
acc **list;
} strcol ;
I access the structure with a pointer:
strcol index;
contato *p;
p = (index.list + index.count);
the question, how i use malloc() in this function?
i try:
(*p)->tel = (char **) malloc(i * sizeof (char*))
p.tel = (char **) malloc(i * sizeof (char*))
&(*p)->tel = (char **) malloc(i * sizeof (char*))
and then as I do the second malloc to save data email or tel
my first post, excuse anything
So this:
(*p)->tel = (char **) malloc(i * sizeof (char*))
allocates space to store i pointers to char - so you can have i telephone number strings. But you don't actually have any space allocated to store those telephone number strings themselves yet. To do that, you need (for the first telephone number):
(*p)->tel[0] = malloc(j);
If this call to malloc() succeeds, you can now store nul-terminated string of length j-1 in the space pointed to by (*p)->tel[0]. You can then do the same for the other pointers in (*p)->tel up to (*p)->tel[i-1].
Using malloc() is simple if code follows:
some_type *p;
p = malloc(number_of_elements * sizeof *p);
if (p == NULL) Handle_OutOfMemory();
So with p.tel,
// p.tel = (char **) malloc(i * sizeof (char*));
p.tel = malloc(i * sizeof *(p.tel));
if (p.tel == NULL) exit(EXIT_FAILURE);
I'm going to assume 'p' is acc *p; (i have no idea what 'contato' is).
Anyway ... the point is to show how memory can be allocated & tel/email data stored/accessed ... Also copied tel #/email id simply to demonstrate ...
Regarding casting void pointer returns from malloc, I've seen arguments for/against ... i cast (malloc's about the only case where i cast).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct accont
{
char **tel; //list of tel
char **email; //list of emails
}acc;
typedef struct _strcol
{
int count; //total of accounts
acc **list;
}strcol;
int main()
{
int iNumAccounts = 5; // Assume there are 5 Accounts.
int iNumTels = 2; // Each Account has 2 Tel #s.
int iNumEmails = 3; // Each Account has 3 Email ids.
strcol index;
acc *p = NULL;
index.list = (acc **)malloc(5 * sizeof(acc *)); // Master list
// of 'acc' pointers i.e. pointer to a set of pointers.
int i, j;
for(i=0; i<iNumAccounts; i++) // Go through the 5 Accounts, one at
// a time ... and allocate & store tel #s/email ids.
{
index.list[i] = (acc *)malloc(sizeof(acc));
p = index.list[i];
p->tel = (char **)malloc(iNumTels * sizeof(char*));
for(j=0; j<iNumTels; j++)
{
p->tel[iNumTels] = (char *)malloc(11 * sizeof (char)); // 10 digit tel # + 1 byte for '\0' ...
strcpy(p->tel[iNumTels], "1234567890");
}
p->email = (char **)malloc(iNumEmails * sizeof(char*));
for(j=0; j<iNumEmails; j++)
{
p->email[iNumEmails] = (char *)malloc(51 * sizeof(char)); // 50 char long email id + 1 byte for '\0' ...
strcpy(p->email[iNumEmails], "kingkong#ihop.yum");
}
}
for(i=0; i<iNumAccounts; i++) // Go through the 5 Accounts, one at a time ... and display.
{
p = index.list[i];
for(j=0; j<iNumTels; j++)
{
printf("Tel # is: %d\n", p->tel[iNumTels]);
}
for(j=0; j<iNumEmails; j++)
{
printf("Email id is: %s\n", p->email[iNumEmails]);
}
printf("----------\n");
}
}
If I've understood the case correct, a stack implementation will be best suited in this case. You can use the standard stack library header (of gcc) or create your own stack implementation suited for your own need.
An example may be something like the code below but you'd better follow the Jerry Cain's videos about the stack procedures (you'll find these videos on youtube: Stanford - Programming Paradigms videos. Stack session should be between video number 6 to 8). link from here
note: be careful! Killing stack elements (via StackPop) will not kill the char strings created by strdup. You'll need to free them individually. These are explained in the videos but I don't exactly remember how (again, you'd find some valuable info in those videos for your case).
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef struct {
char *tel;
char *email;
} account;
typedef struct {
int *ptrElement; // starting address of the stack
int sizeAllocat; // total size allocated
int sizeCurrent; // current size
int sizeElement; // byte length of the stack element
} Stack;
// create a new stack pointer
void StackNew (Stack *s, int sizeElement) {
assert (s->ptrElement > 0);
s->sizeElement = sizeElement;
s->sizeCurrent = 0;
s->sizeAllocat = 4;
s->ptrElement = malloc (4 * sizeElement);
assert (s->ptrElement != NULL);
}
// kills a stack pointer
void StackDispose (Stack *s) {
free (s->ptrElement);
}
// expands stack space
static void StackGrow (Stack *s) {
s->sizeAllocat *= 2;
s->ptrElement = realloc (s->ptrElement, s->sizeAllocat * s->sizeElement);
}
// insert new stack pointer (of type account for example)
void StackPush (Stack *s, void *ptrElement) {
if (s->sizeCurrent == s->sizeAllocat) {
StackGrow (s);
}
void *target = (char *) s->ptrElement + s->sizeCurrent * s->sizeElement;
memcpy (target, ptrElement, s->sizeElement);
s->sizeCurrent++;
}
// pops (deletes) an element from stack
void StackPop (Stack *s, void *ptrElement) {
void *source = (char *) s->ptrElement +
(s->sizeCurrent - 1) * s->sizeElement;
memcpy (ptrElement, source, s->sizeElement);
s->sizeCurrent--;
}
// relocate stack element
void StackRotate (void *first, void *middle, void *after) {
int foreSize = (char *) middle - (char *) first;
int backSize = (char *) after - (char *) middle;
char tmp [foreSize];
memcpy (tmp, first, foreSize);
memmove (first, middle, backSize);
memcpy ((char *) after - foreSize, tmp, foreSize);
}
int main () {
Stack s;
account *acc;
StackNew (&s, sizeof (acc));
// your code here
// example
// acc->tel = strdup("some number");
// acc->email = strdup("some text");
// StackPush(&s, &acc);
...
// StackPop(&s, &acc);
...
...
StackDispose (&s);
return 0;
}
I have two structures:
struct product {
char *title; // Name of the product
char code[8]; // Max. 7 characters of product ID
int stock; // Current stock (number of units)
double price; // Price of a single unit
};
struct product_array {
struct product *arr;
unsigned int count;
};
I am adding products to product_array with function:
void add_product(struct product_array *pa, const char *title, const char *code,
int stock, double price) {
pa->count++;
struct product* nProduct = malloc(sizeof (struct product));
if (!nProduct) free(nProduct);
init_product(nProduct, title, code, stock, price);
pa->arr = realloc(pa->arr, (pa->count) * sizeof (struct product));
if (!pa->arr) free(pa->arr);
pa->arr[pa->count - 1] = *nProduct;
}
void init_product(struct product *pr, const char *title, const char *code,
int stock, double price) {
int titleLen = strlen(title);
int codeLen = strlen(code);
char *aTitle = calloc((1 + titleLen) * sizeof (char), 1);
strncpy(aTitle, title, titleLen);
char* codePtr = strncpy(pr->code, code, codeLen);
if (codeLen <= 7)
*(codePtr + codeLen) = 0;
else
*(codePtr + 7) = 0;
pr->title = aTitle;
pr->stock = stock;
pr->price = price;
}
add_product works like this in main.c
struct product_array pa;
pa.count = 0;
pa.arr = NULL;
struct product p;
init_product(&p, "test", "0000", 1, 0.50);
print_products(&pa);
add_product(&pa, "Product 1", "0000", 0, 10);
add_product(&pa, "Long name, isn't it", "1234567890", 10, 100);
add_product(&pa, "Product 3", "9999999", 0, 20);
print_products(&pa);
remove_all(&pa);
When I am trying to free all allocated memory, I run to problems. Here is remove all function:
int remove_all(struct product_array *pa) {
unsigned int i;
unsigned int until = pa->count;
struct product *prdPtr = pa->arr;
struct product *next;
for (i = 0; i < until; i++) {
next = prdPtr + 1;
free(prdPtr->title);
free(prdPtr); // this raises error
prdPtr = next;
}
if (pa->arr != NULL) {
free(pa->arr);
}
pa->count = 0;
return 1;
}
The for-loop overflows, but I am now trying to figure out the logic of memory freeing in this context.
In remove_all function I want to free all memory of product_array. I am iterating through every (struct)product in array and freeing the memory of title. After freeing memory of title I am trying to free the struct product itself. It works in first iteration, but when I come to second element, the title could be freed but free(prdPtr) raises SIGABRT.
What might I be missing? Why am I able to free the titles of products but not products themselves?
Thank you for help in advance.
The pa->arr is struct product * not struct product **.
So you have allocated memory for pa->arr and you should free it only once. pa->arr[i] is not a pointer, but just a structure.
You shouldn't free it, but you should free any memory allocated to its members like title.
So update your for loop as
...
for (i = 0; i < until; i++) {
next = prdPtr + 1;
free(prdPtr->title); //just free members
prdPtr = next;
}
if (pa->arr != NULL) {
free(pa->arr);
}
...
Edit:
Also note that there is an unnecessary malloc in add_product. Suggested fix:
void add_product(struct product_array *pa, const char *title, const char *code,
int stock, double price) {
struct product *pa_tmp;
pa->count++;
pa_tmp = realloc(pa->arr, (pa->count) * sizeof (struct product));
if (pa_tmp == null) {
/* handle out of memory error */
}
pa->arr = pa_tmp;
init_product(&pa->arr[pa->count - 1], title, code, stock, price);
}
You free the same Memory block twice:
// this makes pdrPtr to an alias of pa->arr
struct product *prdPtr = pa->arr;
for (i = 0; i < until; i++) {
...
free(prdPtr); // free prdPtr a.k.a. pa->arr
...
}
// here you free the same oject again.
free(pa->arr);
Remove the last free(pa->arr);.
I have the following code and am unsure of whether to use structure alignment or memcpy to copy struct A onto the custom "stack" char/byte array.
Is there anything advantageous/disadvantageous about the following two options of code or anything that is just flat out wrong?
The necessary struct/functions.
struct B {
int type;
struct B *prev;
}
struct A {
struct B base;
int n;
struct B *another;
char name[1]; /* Struct hack */
};
void align(char **ptr, int n) {
intptr_t addr = (intptr_t)*ptr;
if(addr % n != 0) {
addr += n - addr % n;
*ptr = (char *)addr;
}
}
Option 1: Struct Assignment
void struct_assignment() {
char *stack = malloc(400*1000);
char *top_of_stack = stack + 3149; /* Just an example */
struct A *var = (struct A *)top_of_stack;
align((char **)&var, sizeof(struct B)); /* Most restrictive alignment member in struct A */
var->base.type = 1;
var->base.prev = NULL;
var->another = (struct base *)var;
char *name = "test";
var->n = strlen(name) + 1;
strcpy(var->name, name);
top_of_stack = (char*)var + sizeof(*var)+ (var->n - 1); /* -1 for name[1] */
}
Option 2: memcpy
void memcpying() {
char *stack = malloc(400*1000);
char *top_of_stack = stack + 3149; /* Just an example */
struct A var;
var.base.type = 1;
var.base.prev = NULL;
var.another = NULL;
char *name = "test";
var.n = strlen(name) + 1;
strcpy(var.name, name);
char *aligned_ptr = top_of_stack;
align(&aligned_ptr, sizeof(struct B)); /* Most restrictive alignment member in struct A */
memcpy(aligned_ptr, &var, sizeof(var) + (var.n - 1); /* -1 for name[1] */
struct A *var_ptr = (struct A*)aligned_ptr;
var_ptr->another = (struct B *)var_ptr;
top_of_stack = aligned_ptr + sizeof(var)+ (var.n - 1); /* -1 for name[1] */
}
Is option 1 even struct assignment?
Will both options result in the same padding and alignment?
Will the endianness of the target architecture affect option 1?
I don't think that this can be called struct assignment. You are assigning to the individual fields.
struct assingment in your case where you are merely interested in initialization of the object on the stack that you are "reserving" could use a temporary:
struct base tmp = {
.type = 1,
.prev = NULL,
// whatever other fields you want to initialize
};
var->base = tmp;
or even more consise by using a compound literal:
var->base = (struct base){
.type = 1,
.prev = NULL,
// whatever other fields you want to initialize
};
Both methods have the advantage of initializing all fields that you
might have forgotten to 0. The for the copy operation itself, let the compiler chose whatever the compiler designer saw fit. Don't mess around with such things unless some careful benchmarking tells you that there is a real problem.