initialize struct from function call - c

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);
// ...
}

Related

What does "request for member in something not a structure or union" mean?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int busqueda_indexada(int a[], int n, int x) {
int elementos[3]; int indice[3];
int g; int i;
int set=0; int ind=0;
for (i=0; i<n-1; i+=3) {
elementos[ind].nombre=a[i]);
elementos[ind].indice = i;
i+=3;
ind++;
}
if (x<elementos[0].boleto) {
return -1;
} else {
for (i=1; i<g-1; i++)
if (x<elementos[i].elem) {
int ini = elementos[i-1].indice;
int fin = elementos[i].indice;
set = 1;
break;
}
}
if (set==0) {
int ini = elementos[G-1].indice;
int fin = n-1;
}
}
struct elementos {
int indice;
char nombre[100];
int boleto;
} elementos a[3];
int main(int argc, char *argv[]) {
struct elementos a[3] = {"marco", 1, "sin asignar", 2, "pedro", 3};
printf("%s y %d", a[2].nombre, a[2].boleto);
busqueda_indexada(a, n, x)
return 0;
}
I don't know how the indexed search can read my structure. I tried everything and always shows
[Error] request for member '' in something not a structure or union
every time I tried to call a structure. Maybe I defined bad my struct or I call it in the wrong way?
With elementos[ind].nombre You try to access a field on elementos[ind], but that itself is a int. .something in only allowed, if elementos[ind] would eithet be a struct or an union.
You use elementos for two different things:
In busqueda_indexada() for a local array of int;
Outside any function for a structure.
The error (among a lot more) is given the first time for elementos[ind].nombre. This is the indth element of the local array, an int, which is clearly no structure.
Please raise the warning level of your compiler to the maximum and correct your code until all errors and warnings are gone.
Use descriptive names for structures and variables.

Multiple threads to find prime factors of integers, segmentation fault

I can't figure out what I am doing wrong with my pointers. It is causing a segmentation fault. I am convinced the problem is rooted in my use of the array of pointers I have and the pthread_join I am using.
The goal is to read multiple integers into a gcc compiler, then print out the integer with all its factors, like this, 12: 2 2 3
I created a struct containing an int array to store the factors of each integer as the factor function pulls it apart and a counter(numfact) to store how many factors there are stored in the array.
I commented out the section at the bottom that prints out the factors.
I think the problem is how I am trying to store the output from the pthread_join in the pointer array, ptr[]. Whenever I comment it out, it does not get the segmentation error.
Either I have my pointers screwed up in a way I don't understand or I can't use an array of pointers. Either way, after many hours, I am stuck.
Please help.
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>
struct intfact
{
long int factors[100];
int numfact;
};
struct intfact *factor(long int y)
{
struct intfact threadfact;
threadfact.numfact = 0;
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
threadfact.factors[threadfact.numfact] = 2;
threadfact.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
threadfact.factors[threadfact.numfact] = i;
threadfact.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
threadfact.factors[threadfact.numfact] = y;
threadfact.numfact++;
}
struct intfact *rtnthred = &threadfact;
return rtnthred;
}
/* Trial Division Function */
void *divde(void *n)
{
long int *num = (long int *) n;
struct intfact *temp = factor(*num);
return temp;
}
/* Main Function */
int main(int argc, char *argv[])
{
pthread_t threads[argc-1];
void *ptr[argc-1];
/* loop to create all threads */
for(int i=0; i < argc; i++)
{
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
}
/* loop to join all threads */
for(int i=0; i < argc; i++)
{
pthread_join(threads[i],(void *) ptr[i]); //THIS POINTER IS THE PROBLEM
}
/* loops to print results of each thread using pointer array*/
//for(int i = 0; i < argc; i++)
//{
// printf("%s: ", argv[i+1]); /* print out initial integer */
// struct intfact *temp = (struct intfact *) ptr[i]; //cast void pointer ptr as struct intfact pointer
// printf("%d", temp->numfact);
//for(int j = 0; j < temp->numfact; j++) /*(pull the numfact(count of factors) from the struct intfact pointer??)*/
//{
// printf("%d ", temp->factors[j]); /* print out each factor from thread struct */
//}
}
}
In my Linux) terminal this code is stored in p3.c
"./p3 12" should yeild "12: 2 2 3"
For starters:
Here
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
you define a long int and pass it as argument to the thread. For example 12
Inside the thread function then
void *divde(void *n)
{
long int *num = (long int *) n;
you treat the long int passed in as pointer to long int.
And then here dereference it
... = factor(*num);
So this *num for example would become *12. That is referencing memory address 12 to read out its content and pass it to factor). Aside the fact that this mostly likely is an invalid address, there would be nothing relevant store, at least nothing your code defined.
To (more or less fix) this do
void *divde(void *n)
{
long int num = (long int) n;
... = factor(num);
The second issues is mentioned in the comment: Multiple threads to find prime factors of integers, segmentation fault
The problem you are trying to solve is a special case of parallel programming, namely that the tasks to be run in parallel are completely independent. In such cases it makes sense to give each task its own context. Here such a context would include the
thread-id,
the thread specific input
as well as its specific output.
In C grouping variables can be done using structures, as your implementation already comes up with for the output of the tasks:
struct intfact
{
long int factors[100];
int numfact;
};
So what is missing is thread-id and input. Just add those for example like this.
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
Now before kicking off the threads define as many contexts as needed:
int main(int argc, char *argv[])
{
size_t num_to_process = argv - 1;
struct context ctx[num_to_process];
then create the threads passing in what is needed, that is input along with space/memory for the output:
for (size_t i = 0; i < num_to_process ; i++)
{
ctx[i].io.input = atol(argv[i]);
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
Inside the thread function convert the void-pointer received back to its real type:
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
Define the processing function to take a pointer to the context specific input/output variables:
void factor(struct inout * pio) /* No need to return any thing */
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pio->input directly. */
Replace all other occurrences of threadfact by pio->output.
Use
return;
}
to leave the processing function.
Then inside the thread function call the processing function:
factor(pio);
Use
return NULL;
}
to leave the thread function.
In main() join without expecting any result from the threads:
/* loop to join all threads */
for (size_t i = 0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
Putting this all together:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
struct intfact
{
long int factors[100];
size_t numfact;
};
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
void factor(struct inout * pio)
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pinout->input directly. */
if (0 == y)
{
return; /* Nothing to do! */
}
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
pio->output.factors[pio->output.numfact] = 2;
pio->output.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
pio->output.factors[pio->output.numfact] = i;
pio->output.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
pio->output.factors[pio->output.numfact] = y;
pio->output.numfact++;
}
return;
}
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
factor(pio);
return NULL;
}
int main(int argc, char *argv[])
{
size_t num_to_process = argc - 1;
struct context ctx[num_to_process];
for (size_t i = 0; i < num_to_process; i++)
{
ctx[i].io.input = atol(argv[i+1]);
if (!ctx[i].io.input)
{
fprintf(stderr, "COnversion to integer failed or 0 for '%s'\n", argv[i]);
}
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
/* loop to join all threads */
for (size_t i=0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
/* loops to print results of each thread using pointer array*/
for(size_t i = 0; i < num_to_process; i++)
{
printf("%ld: ", ctx[i].io.input); /* print out initial integer */
printf("%zu factors --> ", ctx[i].io.output.numfact);
for(size_t j = 0; j < ctx[i].io.output.numfact; j++)
{
printf("%ld ", ctx[i].io.output.factors[j]); /* print out each factor from thread struct */
}
putc('\n', stdout);
}
}

Printing Wrong Data

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

Getting seg fault when assigning random float value in a loop from rand()

I cannot figure out why my code works only one way and it is driving me crazy because it just should work.Whole code so far:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <time.h>
#define MAGIC_CONSTANT 73.
int Check_Parameters(int argc, char **argv){
int i=0;
if(argc > 3){
printf("You have entered more than 2 arguments!\n");
}
do{
if(isdigit(argv[2][i]) == 0){
printf("Second argument should be number!\n");
return 0;
}
i++;
}while(argv[2][i] != 0);
return 1;
}
int Write_Sequence(char **argv,int Handle){
char *length;
float *values,help;
unsigned int i,j,index;
index = atoi(argv[2]);
for(i=0; i<index; i++){
*length = (char)(rand()%11+10);
if(write(Handle,length,1) == -1){
printf("Something went wrong during Index writing\n%s\n",strerror(errno));
return 0;
}
printf("Value is: %u\n",*(unsigned int *)length);
values = malloc(*length*sizeof(float));
if(values == NULL){
printf("Memory allocation for values failed\n");
return 0;
};
for(j=0; j<*length; j++){
help = (rand()%200)/MAGIC_CONSTANT;
values[j] = (float)(rand()%200)/MAGIC_CONSTANT;
printf("%lf\n",values[j]);
}
if(write(Handle,(char*)values,sizeof(float)*(*length)) == -1){
printf("Something went wrong during value writing\n%s\n",strerror(errno));
return 0;
};
free(values);
}
return 1;
}
int main(int argc, char **argv){
int Handle;
char *citaj;
srand(time(NULL));
Check_Parameters(argc,argv);
Handle = open(argv[1], O_RDWR | O_CREAT);
Write_Sequence(argv,Handle);
close(Handle);
return 0;
}
I want to fill my allocated memory with floats. The thing is that this code does not work:
for(j=0; j<*length; j++){
values[j] = (rand()%200)/MAGIC_CONSTANT;
}
But this one does without any problem:
for(j=0; j<*length; j++){
help = (rand()%200)/MAGIC_CONSTANT;
values[j] = help;
}
MAGIC_CONSTANT = 73.
The thing is it only works when I first assign it to my help variable and then to the memory and whenever I assign it right away it gives me segmentation fault. What is wrong with that rand() function?
Thanks!
You declare length as a char *, but you never give it a value. You then try to dereference the pointer by assigning to *length. That invokes undefined behavior. In your case, this manifests as a segfault in your code without help but appears to work when you do use help.
In this code, you don't need length to be a pointer. Instead, declare it as a char and assign to it directly. Then when calling write, take its address.
int Write_Sequence(char **argv,int Handle){
// declare as char
char length;
float *values,help;
unsigned int i,j,index;
index = atoi(argv[2]);
for(i=0; i<index; i++){
// assign directly to length
length = (char)(rand()%11+10);
// pass address of length to write
if(write(Handle,&length,1) == -1){
printf("Something went wrong during Index writing\n%s\n",strerror(errno));
return 0;
}
...
The statement:
*length = (char)(rand()%11+10);
You are attempting to assign the type-casted output of rand() into an uninitialized pointer. I am not sure what you intended to use this for, but if your compiler is set properly, this should throw warnings. (uninitialized pointer)
Other things to consider, 1) for how its used, length does not need to be a pointer. 2) when using rand(), it is recommended that srand() be called first to seed the pseudo randomizer rand(). Once you do these few things, your code at least starts to work. There are other things you can do to optimize, but a code segment with these changes is below.
#define MAGIC_CONSTANT 73
int main(void)
{
char length = 0;
float *values,help;
unsigned int i,j;
srand(clock());
length = (char)(rand()%11+10);
values = malloc(length*sizeof(float));
for(j=0; j<length; j++)
{
values[j] = (rand()%200)/MAGIC_CONSTANT;
}
return 0;
}

How can I dynamically fill an array of pointers to structs that I have made?

First, some background, I'm writing a file server for my systems programming class. What I have to do is write 4 client programs and a server to edit the directory of files client side. I've figured out how to actually do the transferring of the files client side, as well as how to actually get them through the socket, what I'm having a hard time doing is storing the files on the server. To try and solve this problem I've created 2 structs:
A FileSlot struct to store the file's name and contents in memory:
#ifndef __FILESLOT_H__
#define __FILESLOT_H__
#include "csapp.h"
typedef struct FILESLOT {
char *filename;
char *contents;
uint32_t length;
} FileSlot;
#endif
and a FileDrawer struct in order to actually keep track of the files on the server as I have to be able to add, remove, and list them:
#ifndef __FILEDRAWER_H__
#define __FILEDRAWER_H__
#include "csapp.h"
#include "fileslot.h"
typedef struct FILEDRAWER {
FileSlot* files[100];
uint32_t drawerSize;
} FileDrawer;
void new_fd(FileDrawer *fd);
uint32_t get_size(FileDrawer *fd);
void add_file(FileDrawer *fd, FileSlot *fs);
void rem_file(FileDrawer *fd, int index);
int search_files(FileDrawer *fd, char *name);
#endif
Basically I'm using these structs in a server loop, as the server receives the "put" command, I want the server to create a FileSlot, and stick it into the FileDrawer. In the past few days I've looked through the forums and so far learned that I need to use malloc(), which I'm a bit hazy on, but if I've learned correctly, I can create a pointer to a FileSlot allocated with malloc(), fill it with the necessary information, and then point one of the files[] elements from FileDrawer at the newly allocated FileSlot:
#include "filedrawer.h"
#include "fileslot.h"
int main(int argc, char** argv) {
FileDrawer *fdp = (FileDrawer*)malloc(sizeof(FileDrawer));
new_fd(fdp);
int i;
while (i < 5) {
uint32_t length = i;
FileSlot* fsp = (FileSlot*)malloc(sizeof(FileSlot));
fsp->filename = "file name";
fsp->contents = "contents";
fsp->length = length;
add_file(fdp, fsp);
i++;
}
for(i = 0; i < fdp->drawerSize; i++) {
printf("File Name %s \n", fdp->files[i]->filename);
}
free(fdp);
return 1;
}
However This doesn't seem to work, I get really strange output from the print loop.
ALSO: Here's the implementations for my FileDrawer functions, in case I've mistyped anything here as well
void new_fd(FileDrawer* fdp) {
FileDrawer fd;
fd = *fdp;
fd.drawerSize = 0;
*fdp = fd;
}
uint32_t get_size(FileDrawer* fdp) {
return fdp->drawerSize;
}
void add_file(FileDrawer* fdp, FileSlot *fs) {
FileDrawer fd = *fdp;
fd.files[fd.drawerSize] = fs;
fd.drawerSize++;
*fdp = fd;
}
void rem_file(FileDrawer* fdp, int index) {
FileDrawer fd;
fd = *fdp;
int i;
for(i = index; i < fd.drawerSize; i++) {
fd.files[i] = fd.files[i+1];
}
fd.drawerSize--;
*fdp = fd;
}
int search_files(FileDrawer* fdp, char *name) {
int i;
int index = -1;
for(i = 0; i < fdp->drawerSize; i++) {
if ((fdp->files[i]->filename) == name) {
index = i;
}
}
return index;
}
EDIT: I went in and fixed the mallocs, and removed the inefficiencies as suggested, so thanks for that! Now, my fdtest exits in a SEGFAULT at the first strcpy, and I can't figure out why. Any ideas?
Here's your main problem:
int i;
while (i < 5) {
You fail to initialize i before using it. Because it is uninitialized, it's value is indeterminate and attempting to read it causes undefined behavior.
Initialize i to 0 and it will behave properly.
int i = 0;
while (i < 5) {
Besides this, you have some inefficiencies in your code.
In new_fd and add_file, you copy the contents of a dereferenced pointer into a local variable, modify the local, then copy the contents back. That's unnecessary work. Just work directly on the passed-in pointer.
void new_fd(FileDrawer* fdp) {
fdp->drawerSize = 0;
}
void add_file(FileDrawer* fdp, FileSlot *fs) {
fdp->files[fdp->drawerSize] = fs;
fdp->drawerSize++;
}
You can perform similar changes in rem_file.
Also, don't cast the return value of malloc, as it can hide subtle bugs.

Resources