So I'm trying to simulate a cache. Right now, I created structs for the blocks and the sets and created their constructors. When the constructor for cache set are activated it initilize all of the tags and valid bits to 0. However, I keep getting garbage data printed out for the tags.I'm probably set up my pointer incorrectly, but I having problems figuring out what.
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
uint64_t tag;
unsigned int valid_bit;
}block;
typedef struct
{
unsigned int set_bit;
unsigned int number_of_blocks;
block * blocks;
}cache_set;
block *make_A_BLOCK(uint64_t tg, unsigned int v_b)
{
block *b = malloc(sizeof(block));
b->tag = tg;
b->valid_bit = v_b;
return b;
}
void change_tag(block *b,uint64_t t_g){b->tag = t_g;}
void change_bit(block *b,unsigned int v_b){b->valid_bit = v_b;}
uint64_t return_tag(block *b){ return b->tag;}
unsigned int return_bit(block *b){ return b->valid_bit;}
cache_set *make_A_CACHE_SET(unsigned int s_b, unsigned int n_b)
{
int i;
//uint64_t blank = 0;
cache_set *c_s = malloc(sizeof(cache_set));
c_s->set_bit = s_b;
c_s->number_of_blocks = n_b;
block *blocks = malloc(n_b * sizeof(block));
for (i=0; i < n_b; i++)
{
blocks[i].tag = 0;
blocks[i].valid_bit = 0;
}
free(blocks);
return c_s;
}
void print_cache_set(cache_set *c_s)
{
int i;
printf("Number of Cache Sets: %d \r\n",c_s->number_of_blocks);
for (i= 0; i < c_s->number_of_blocks ; i++)
{
printf("Block %d ",i);
printf(" Block Tag " "%" PRIu64, return_tag(&(c_s->blocks[i])));
//printf(" Block Bit %d \r\n", blocks[i].valid_bit);
}
}
int main(void)
{
cache_set *test = make_A_CACHE_SET(0,10);
print_cache_set(test);
printf("done");
return 0;
}
Example
When making a cash_set, you allocate blocks and assign the pointer to them to a local variable, and then you initialize the blocks one after the other.
But then, instead of letting the c_s->blocks point to this initialized list of blocks, you deallocate them with free(blocks).
So I'd suggest to replace free(blocks) by c_s->blocks = blocks
Related
Feel like im taking crazy pills just trying to do literally the simplest stuff I can imagine in C. Any help would be extremely appreciated. why does this work?
#include <stdio.h>
#include <stdlib.h>
#define Q_LIMT 100
typedef struct servers
{
int id;
int num_in_Q;
int server_status;
}SERVER;
void initialize(SERVER *s);
void initialize(SERVER *s)
{
int i=0,j=0;
for(i=0; i<2; i++) { //i=0; i=1
s[i].id = i; // 0, 1
s[i].num_in_Q = i*i + 1; // 1, 2
s[i].server_status = i+i + 2; // 2, 4
} // the bracket was missing
}
int main()
{
int i;
SERVER serv[2];
initialize(serv);
for(i=0; i<2; i++) {
printf("server[%d].id = %d\n", i, serv[i].id);
printf("server[%d].num_in_Q = %d\n", i, serv[i].num_in_Q);
but this throws away the initialized struct?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
'''
int POINTERS_PER_INODE = 5;
struct Inode {
int valid;/* 0 == invalid, 1 == valid*/
int size;
int Blocks [5];
};
int InodeToString(char * InodeString, struct Inode iNode){
char * blockBuffer;
sprintf(InodeString, "%d", iNode.valid);
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
blockBuffer = malloc(8);
sprintf(blockBuffer, "%d", iNode.Blocks[i]); //no valid pointers yet
strcat(InodeString,blockBuffer);
free(blockBuffer);
}
return 0;
}
int initializeInode(struct Inode iNode){
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
iNode.Blocks[i] = -1; //no valid pointers yet
}
iNode.valid = 0; //initialized as invalid inode
return 0;
}
int main() {
struct Inode iNode1;
initializeInode(iNode1);
char * InodeString;
InodeString = malloc(20);
InodeToString(InodeString, iNode1);
printf("%s", InodeString);
free(InodeString);
iNode1.valid = 1;
InodeString = malloc(20);
InodeToString(InodeString, iNode1);
printf("%s", InodeString);
return 0;
}
This is test code btw, so the includes probably dont make sense. stack overflow says I dont have enough details so I guess I have to keep typing sentences. Let me know if theres any details that would make this more clear. its for a basic super simplified file system simulation project. it seemed in a previous version when I initialized the inode outside of the function, I was able to pass the string into the string function, assign it values, not use it as the return value and still end up on the other side of the function with an updated string.
As is normal in C, arguments to a function are passed by value. The object called iNode in initializeInode is local to that function, and changes to it have no effect on any other object in the program. If you want a function to modify an object that's local to the caller, you have to pass a pointer to it, and dereference that pointer to get at the caller's object.
So what you probably want is:
int initializeInode(struct Inode *iNode){
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
iNode->Blocks[i] = -1; //no valid pointers yet
}
iNode->valid = 0; //initialized as invalid inode
return 0;
}
int main() {
struct Inode iNode1;
initializeInode(&iNode1);
// ...
}
Well I am wanting to change the way my structures are written, currently I use array and I need to limit its use, but I wanted a way to create a dynamic array that is the size of the reading done, without always having to edit the array value.
Current Code:
struct sr_flag {
int value_flag;
};
struct er_time {
int value_time;
};
struct se_option {
struct sr_flag flag[50];
struct er_time time[50];
};
struct read_funcs
struct se_option *option;
void (*option_func) (void);
...
}
struct read_funcs func_;
struct read_funcs *func;
int sr_flags(int i, int fg, int val) {
if(i < 0)
return 0;
return func->option[i].flag[fg].value_flag = val;
}
void option_func(void) {
struct se_option fnc;
fnc.option = malloc(500 * sizeof(*(fnc.option)));
}
void read_fnc() {
func = &func_;
func->option = NULL;
func->option_func = option_func;
}
I look for a way to remove the array amount [50] instead each time the sr_flags function is executed the limit is raised
Example: sr_flags function executed 1x array would be [1] if executed 2x would be [2]
I also think about doing the same with the option_func function
I tried using the following more unsuccessfully
struct se_option {
struct sr_flag *flag;
struct er_time time[50];
};
int sr_flags(int i, int fg, int val) {
if(i < 0)
return 0;
func->option[i].flag = malloc(1 * sizeof(*(func->option[i].flag)));
return func->option[i].flag[fg].value_flag = val;
}
int main () {
for(int i < 0; i < 10; i++)
sr_flags(i, 1, 30);
return 0;
}
I'm not 100% certain on what it is you want but I think you just want to call realloc and increase the size by the amount you provide. And that's very easy to do, as for the values you want with the arrays I'm not sure so I just used a placeholder value.
#include <stdio.h>
#include <stdlib.h>
struct sr_flag {
int value_flag;
};
struct er_time {
int value_time;
};
struct se_option {
struct sr_flag* flag;
struct er_time* time;
};
void allocateflags(struct se_option* options, int size, int val){
options->flag = realloc(options->flag, size*sizeof(struct sr_flag));
struct sr_flag* flag = options->flag+size-1;
flag->value_flag = val;
}
void allocatetime(struct se_option* options,int size, int val){
options->time = realloc(options->time, size*sizeof(struct er_time));
struct er_time* time = options->time+size-1;
time->value_time = val;
}
void displayflagvalues(struct se_option* options,int size){
for(int index = 0; index < size ; ++index){
printf("flag: %i\n",options->flag[index].value_flag);
}
}
void displaytimevalues(struct se_option* options, int size){
for(int index = 0; index < size ; ++index){
printf("time: %i\n",options->time[index].value_time);
}
}
int main(){
struct se_option options = {0};
for(int index = 0; index < 10; ++index){
allocateflags(&options, index,index);
allocatetime(&options, index,index);
}
displayflagvalues(&options, 10);
displaytimevalues(&options,10);
return 0;
}
The code creates an se_option structure wheren sr_flag and er_time pointers are null. Then there's two functions one allocateflags and the other allocatetime, both of which call realloc with the size you provide. When you call realloc, all previous memory is copied over to the new array. Also free is called automatically by realloc.
This step
struct sr_flag* flag = options->flag+size-1;
flag->value_flag = val;
struct er_time* time = options->time+size-1;
time->value_time = val;
Is slightly redundant but it was just to show the newest array can hold the value. If you understand pointer arithmetic, all its doing is incrementing the pointer to the last position then subtracting 1 struct size and setting that value. Basically setting the value of the final array in the pointer.
I my code i call the insert function and it passes a pointer to the struct (table) and the insert function recieves a pointer and does some stuff and returns it again. But running the code gives segmentation fault. when i try to access the values in the struct array using the pointer passed.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define __USE_BSD
#include <string.h>
#include "speller.h"
#include "dict.h"
typedef struct
{ // hash-table entry
Key_Type element; // only data is the key itself
enum {empty, in_use, deleted} state;
} cell;
typedef unsigned int Table_size; // type for size-of or index-into hash table
struct table
{
cell *cells; Table_size table_size; // cell cells [table_size];
Table_size num_entries; // number of cells in_use
// add anything else that you need
};
int hashfunc(Key_Type k, Table_size size)
{
printf("enterd\n");
char * d = k;
int hash = 0;
int c;
printf("%s\n", d);
printf("wtf??\n");
while (c = *d++)
{
printf("maybehere??\n");
hash = hash + c;
}
hash = hash%size;
printf("%d\n", hash);
return hash;
}
Table initialize_table (Table_size size)
{
Table t = malloc(sizeof(struct table));
t->table_size = size;
cell hash_table[size];
for (int i=0; i<size; i++)
{
hash_table[i].state = empty;
hash_table[i].element = "-";
//printf("initialised\n");
}
t->num_entries = 0;
t->cells = hash_table;
/*for (int i = 0; i < t->table_size; i++)
{
printf("%d %s\n", i, (t->cells + i)->element);
}*/
return t;
}
int a = 0;
Table insert (Key_Type k, Table t)
{
//printf("insert called %d\n", a);
printf("%d\n", t->table_size);
//printf("%s\n", (t->cells + 2)->element);
// as soon as program reaches here i get output like - 1 (NULL)
2 (NULL) and then segmentation fault
for (int i = 0; i < t->table_size; i++)
{
printf("%d %s\n", i, (t->cells + i)->element);
}
a++;
printf("%s\n", k);
int hash_code = hashfunc(k, t->table_size);
// Linear Probing
printf("im here\n");
while(strcmp((t->cells + hash_code)->element,"-") != 0)
{
if (strcmp((t->cells + hash_code)->element,k) == 0)
{
printf("return at if\n");
return t;
}
else if (hash_code == (t->table_size - 1))
hash_code = 0;
else
hash_code++;
}
(t->cells + hash_code)->element = k;
(t->cells + hash_code)->state = in_use;
t->num_entries += 1;
printf("return at end with value %s\n", k);
printf("inserted value %s\n", (t->cells + hash_code)->element);
return t;
}
Boolean find (Key_Type k, Table t)
{
return FALSE;
}
void print_table (Table t)
{
Table_size size = t->table_size;
for (int i = 0; i<size; i++)
{
if (strcmp((t->cells + i)->element,"-") != 0)
printf("%d %s\n", i, (t->cells + i)->element);
}
}
void print_stats (Table t)
{
}
void main()
{
Table table;
Table_size table_size = 19;
int a = 5;
Key_Type input[5] = {"a","b","ab","abc","abcd"};
table= initialize_table (table_size);
//printf("%s\n", input[1]);
while (a)
{
table= insert("a",table);
a--;
}
printf("printing table\n");
print_table(table);
}
this is the dict.h code
typedef char* Key_Type;
typedef struct table* Table; // allows different definitions of struct table
Table initialize_table (); // allows different parameters
Table insert (Key_Type, Table);
Boolean find (Key_Type, Table);
void print_table (Table);
void print_stats (Table);
This is the speller.h code
typedef enum {FALSE, TRUE} Boolean;
extern int verbose; // used to control monitoring output
extern int mode; // used to control your algorithm
extern char *prog_name; // used by check
void check (void *memory) ; // check result from strdup, malloc etc.
I believe i dont understand how the pointers work in this program.
Here is the problem,
cell hash_table[size];
and then, you make t->cells point to hash_table but hash_table is a local variable in the initialize_table() function, so it's destroyed/deallocated when the function returns and no longer accessible after it returns.
You should allocate it on the heap too, like this
cell *hash_table;
hash_table = malloc(size * sizeof(*hash_table));
if (hash_table == NULL)
return NULL; // Probably free `t' so that no memory leaks
// happen
Accessing such a local variable that was allocated in the stack frame of a function, after that function returns is undefined behavior, the problem could happen somewhere else in the code or when accessing the pointer pointing to the deallocated data.
A side note
Be consistent with naming, and unambigous, you used a weird CamelCase and underscore combination, it doesn't matter if it's weird or not, keep it and preserve it throughout the code — respect your own style. And call the cell typedef: Cell instead.
Also, always check the return value of malloc() which returns NULL on error (allocation failure), you should write code as if all the bad things will happen, because they do.
And finally, never typedef a pointer. It doesn't help whatsoever, it only obscures the fact that a declaration is that of a pointer.
I'm having an issue understanding this, my code below:
#include <stdio.h>
#include <stdlib.h>
typedef struct mee test;
typedef struct aa fill;
struct aa {
int c;
fill *point;
};
struct mee {
char name;
fill **a;
int b;
};
static fill **store;
static fill *talloc(int tsize);
static int mem;
static int ptr;
static fill *talloc(int tsize)
{ int temp;
temp = ptr;
ptr++;
mem = mem + tsize;
store = realloc(store, mem*sizeof(fill));
store[temp] = malloc(sizeof(fill));
return store[temp];
}
int main() {
test *t;
t = malloc(sizeof(test));
t->a = malloc(sizeof(fill *)*10);
printf("where\n");
for(int i= 0; i < 10; i++) {
t->a[i] = talloc(1);
}
printf("%d\n", store[9]->c); //Problem here
return 0;
}
excuse the terrible names, just some test code for a larger project. This code compiles and runs fine. if I set the code:
printf("%d\n", store[9]->c);
store[0-7] I get 0 as the output, though why does 8-9 give me some gibberish negative number? I'm assuming its a loss it the pointer somewhere.
How can I correct this?
For some background, this is to store pointers to struct in a array so I can free them a lot easier later.
I'm currently trying to use msgpack in a project written in C. I'm using msgpack for the purpose of serializing the contents of a struct, which is then to be sent over the network, and deserialized back into a corresponding struct on the other side.
Condensed version of what I'm trying to do:
#include <stdio.h>
#include <msgpack.h>
#include <stdbool.h>
typedef someStruct{
uint32_t a;
uint32_t b;
float c;
} someStruct;
int main (void){
someStruct data;
/* ... Fill 'data' with some data for test purposes ...*/
msgpack_sbuffer* buff = msgpack_sbuffer_new();
msgpack_packer* pck = msgpack_packer_new(buff, msgpack_sbuffer_write);
someStruct* structs = malloc(sizeof(someStruct) * 10);
/* ... Fill 'structs' with members containing test data ... */
// Serialize
msgpack_pack_array (pck, 10);
int i;
for(i = 0 ; i < 10 ; i++){
msgpack_pack_array (pck, 3);
msgpack_pack_uint32 (pck, structs[i].a);
msgpack_pack_uint32 (pck, structs[i].b);
msgpack_pack_float (pck, structs[i].c);
}
free(structs);
msgpack_packer_free(pck);
// Deserialize
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
bool deserialize_success = msgpack_unpack_next
(&msg, buff->data, buff->size, NULL);
if(!deserialize_success) /* Error */
msgpack_object obj = msg.data;
msgpack_object_print(stdout,obj); // This seems to work perfectly, indicating serialize / deserialize works as intended...
someStruct deserialized_data;
/* Insert code to extract and cast deserialized data to 'deserialized_data */
// Clean
msgpack_sbuffer_free(buff);
msgpack_packer_free(pck);
return 0;
}
The code listed is more or less ripped straight from here, which seems to be one of very few resources on msgpack-c.
Can anyone point me in the right direction as to a way to 'recreate' the original struct on the other side of the wire? The only way I've found to actually utilize the deserialized data, is to use the msgpack_object_print() call to print from the messagepack_object. This does, however seem to work, so I'm certain the data is there.
Do I need to somehow loop through the serialized data and use msgpack_unpack_next() with an offset to retrieve each someStruct member? Using memcpy to a local byte buffer?
Any help is greatly appreciated!
Please find below a rewritten version that illustrates how to pack / unpack your data.
The whole idea is to pack each successive field of your struct, in a contiguous fashion, and apply (of course), the same logic at unpack time.
Right after pack, you are free to use the buffer the way you want (e.g send over the network, save on-disk, etc).
#include <stdio.h>
#include <assert.h>
#include <msgpack.h>
typedef struct some_struct {
uint32_t a;
uint32_t b;
float c;
} some_struct;
static char *pack(const some_struct *s, int num, int *size);
static some_struct *unpack(const void *ptr, int size, int *num);
/* Fixtures */
some_struct ary[] = {
{ 1234, 5678, 3.14f },
{ 4321, 8765, 4.13f },
{ 2143, 6587, 1.34f }
};
int main(void) {
/** PACK */
int size;
char *buf = pack(ary, sizeof(ary)/sizeof(ary[0]), &size);
printf("pack %zd struct(s): %d byte(s)\n", sizeof(ary)/sizeof(ary[0]), size);
/** UNPACK */
int num;
some_struct *s = unpack(buf, size, &num);
printf("unpack: %d struct(s)\n", num);
/** CHECK */
assert(num == (int) sizeof(ary)/sizeof(ary[0]));
for (int i = 0; i < num; i++) {
assert(s[i].a == ary[i].a);
assert(s[i].b == ary[i].b);
assert(s[i].c == ary[i].c);
}
printf("check ok. Exiting...\n");
free(buf);
free(s);
return 0;
}
static char *pack(const some_struct *s, int num, int *size) {
assert(num > 0);
char *buf = NULL;
msgpack_sbuffer sbuf;
msgpack_sbuffer_init(&sbuf);
msgpack_packer pck;
msgpack_packer_init(&pck, &sbuf, msgpack_sbuffer_write);
/* The array will store `num` contiguous blocks made of a, b, c attributes */
msgpack_pack_array(&pck, 3 * num);
for (int i = 0; i < num; ++i) {
msgpack_pack_uint32(&pck, s[i].a);
msgpack_pack_uint32(&pck, s[i].b);
msgpack_pack_float(&pck, s[i].c);
}
*size = sbuf.size;
buf = malloc(sbuf.size);
memcpy(buf, sbuf.data, sbuf.size);
msgpack_sbuffer_destroy(&sbuf);
return buf;
}
static some_struct *unpack(const void *ptr, int size, int *num) {
some_struct *s = NULL;
msgpack_unpacked msg;
msgpack_unpacked_init(&msg);
if (msgpack_unpack_next(&msg, ptr, size, NULL)) {
msgpack_object root = msg.data;
if (root.type == MSGPACK_OBJECT_ARRAY) {
assert(root.via.array.size % 3 == 0);
*num = root.via.array.size / 3;
s = malloc(root.via.array.size*sizeof(*s));
for (int i = 0, j = 0; i < root.via.array.size; i += 3, j++) {
s[j].a = root.via.array.ptr[i].via.u64;
s[j].b = root.via.array.ptr[i + 1].via.u64;
s[j].c = root.via.array.ptr[i + 2].via.dec;
}
}
}
msgpack_unpacked_destroy(&msg);
return s;
}