here is two c program to implement queue data structure in simple form
the first:
define one queue and it's work perfectly
the second:
define multiple queues and it's crash at execution
functions are the same in both programs except the main() were the implementation
are different little bit.
So the question here: why the second code not working?
* here is the codes *
code 1:
/*
Single queue -- this work perfectly
*/
#include <stdio.h>
#define Q_MAX_SIZE 255
struct queue {
int* pointer;
int* currentValue;
int max, count, theQueue[Q_MAX_SIZE];
};
//prototyps
void initQueue(struct queue*);
unsigned short pushQueue(struct queue*, int);
int* popQueue(struct queue*);
int main(void) {
int j;
struct queue q;
initQueue(&q);
for (j = 0; j < 6; j++)
pushQueue(&q, j);
int* inputobj = popQueue(&q);
while (inputobj != NULL)
{
printf("%d ", *inputobj);
inputobj = popQueue(&q);
}
printf("\n\ndone..Queue is empty\n");
return 0;
}
//#################################
void initQueue(struct queue *Q)
{
Q->pointer = Q->theQueue;
Q->max = Q_MAX_SIZE;
Q->count = 0;
}
unsigned short pushQueue(struct queue *Q, int input) {
if (Q->count < Q->max)
{
*Q->pointer = input;
Q->pointer++;
Q->count++;
return 1;
}
else
return 0;
}
//#################################
int* popQueue(struct queue *Q) {
int i;
if (Q->count > 0)
{
*Q->currentValue = *Q->theQueue;
Q->pointer--;
Q->count--;
for (i = 0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return Q->currentValue;
}
else
NULL;
}
code 2:
/*
Multiple queues -- this not work and crash at execution
*/
#include <stdio.h>
#define Q_MAX_SIZE 255
struct queue {
int* pointer;
int* currentValue;
int max, count, theQueue[Q_MAX_SIZE];
};
//prototyps
void initQueue(struct queue*);
unsigned short pushQueue(struct queue*, int);
int* popQueue(struct queue*);
int main(void) {
int i, j;
struct queue obj[5];
for(i=0; i<5; i++)
{
initQueue(&obj[i]);
for(j = 0; j<3; j++)
{
pushQueue(&obj[i], j);
}
}
for(i=0; i<5; i++)
{
printf("Queue[%d]:\n", i);
int* inputobj;
inputobj = popQueue(&obj[i]);
while(inputobj != NULL)
{
printf("Queue[No.%d] = %d\n", i, *inputobj);
inputobj = popQueue(&obj[i]);
}
putchar('\n');
}
return 0;
}
//#################################
void initQueue(struct queue *Q)
{
Q->pointer = Q->theQueue;
Q->max = Q_MAX_SIZE;
Q->count = 0;
}
unsigned short pushQueue(struct queue *Q, int input) {
if (Q->count < Q->max)
{
*Q->pointer = input;
Q->pointer++;
Q->count++;
return 1;
}
else
return 0;
}
//#################################
int* popQueue(struct queue *Q) {
int i;
if (Q->count > 0)
{
*Q->currentValue = *Q->theQueue;
Q->pointer--;
Q->count--;
for (i = 0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return Q->currentValue;
}
else
NULL;
}
Update: the problem was in initQueue() and it's solved by allocating memory
for Q->currentValue here is the function after editing:
void initQueue(struct queue *Q)
{
Q->currentValue = malloc(sizeof(int));
Q->pointer = Q->theQueue;
Q->max = Q_MAX_SIZE;
Q->count = 0;
}
As both answers already stated, the problem is that Q->current_value has never been assigned a value to and so it points to an undefined address and every dereferencing like *Q->currentValue = .. is undefined behaviour. The fact that code 1 seemingly works doesn't prove anything else because due to the nature of UB no behaviour is guaranteed, your program may or may not crash (or your dog may explode, dragons fly out of your nose ... :-) )
Of course there are multiple solutions that all mean something different:
if currentValue should just hold a copy of a certain value, it could be int currentValue instead of int *... and the assignnment would be
Q->currentValue = *Q->theQueue;
and the return statement would be return &Q->currentValue. In that case you would return a pointer to the original value of theQueue[0]
if you want to point to the location in theQueue, Jim's anser tells the correct way:
Q->currentValue = Q->theQueue;
In that case you yould return a pointer to the new value of theQueue[0] (which may be what you don't want)
you could allocate memory to Q->currentValue my malloc( sizeof (int) ); and then leave the assignment as it is. In that case you would return a pointer to the original value of theQueue[0] like in (1)
This is actually are really subtle problem, I think. The problem (I THINK) is this line in popqueue():
*Q->currentValue = *Q->theQueue;
I double-checked and your initial code (no array) also seg faults. It does not work as you have said. You should have written:
Q->currentValue = Q->theQueue;
C can be a bit understanding with pointers and assign things appropriately, but when you added another level (arrays) I think the assignment was forced into something that didn't work. That's my take on it. I think I will put up a bounty so you can get a better answer.
first of all, I would not try to put code like this one in production. Things can be done more simple, clear, performant and less error prone.
I've "fixed" your program by changing things in as little as possible places. It must be clear that this doesn't make things more elegant. Only rethinking and rewriting would make things more elegant.
The error you have (both in the first and the second program) is the routine popQueue.
You return nothing in the else clause. You should "return NULL". This is at least sloppy programming.
The routines return 1 2 3 4 5 5 and 1 2 2 for a queue. This is because Q->CurrentValue points to the first place in the theQueue array, and you shift up all values. This means that CurrentValue defacto points to the next value.
The solution (again: it's not elegant, nor would I put it in production, but it is with minimal change to the original) to your problem is:
Change in the struct (to hold the real CurrentValue)
struct queue
{
int* pointer;
int currentValue;
int max, count, theQueue[Q_MAX_SIZE];
};
Change the routine popQueue
int* popQueue(struct queue *Q) {
int i;
if (Q->count > 0)
{
Q->currentValue = *Q->theQueue;
Q->pointer--;
Q->count--;
for (i = 0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return &(Q->currentValue);
}
else
return NULL;
}
Kind regards,
PB
The location Q->currentValue cannot be accessed, that is the problem. It is not allocated.
The solution is to allocate the right portion of memory in the init routine:
Q = malloc(sizeof(struct queue));
perhaps also initializing the value of all your variables after that.
Related
I am writing a program that takes integers as command line arguments. For each of these numbers I have to create a thread which calculates Fibonacci series up to that number. That function returns a struct pointer to the main where the data is printed.
Now, I have correctly done the fib calculations and checked them by printing the series within the function.
The problem arises when I try to return the struct pointer created within the thread function and use it to print the data in the main.
typedef struct thread_func_param
{
int *fib;
int size;
} thread_func_param;
//===================================================
void *fibGen(void *parameters)
{
int num = atoi(parameters);
struct thread_func_param *p;
p = malloc (sizeof (thread_func_param));
p->size = fibSize(num);
p->fib = malloc(sizeof(int)* p->size);
//Fibonacci Calculations
//..
//.
return (void *) p;
//pthread_exit((void *) p);
}
//===================================================
int main(int argc, char* argv[])
{
void* thread_result;
thread_func_param* p = malloc( sizeof(thread_func_param));
assert(argc > 1);
int noOfThreads = argc - 1;
printf("No of Thread = %d\n", noOfThreads);
pthread_t *threadID = malloc (sizeof (pthread_t) * noOfThreads);
pthread_attr_t attributes;
pthread_attr_init(&attributes);
int i, j;
for(i = 0; i < noOfThreads; i++)
{
pthread_create(&threadID[i], &attributes, fibGen, argv[i+1]);
pthread_join(threadID[i], thread_result);
//HOW TO USE THE RETURNED DATA?
for (j = 0; j< ((thread_func_param*)thread_result->size)-1; j++)
printf(" %d ", (thread_func_param*)thread_result->fib[j]);
}
return 0;
}
The solution that I use, in the end, to print the data gives error of dereferencing a void pointer (I am new with C). How can I correct it?
Two issues here:
pthread_join() takes a void** as 2nd parameter. The code passes a void* only.
To cast a pointer wrap it into parenthesis. Here the cast
(thread_func_param*)thread_result->size
refers to size not to thread_result. So what you want is
((thread_func_param*)thread_result)->size
However a nice and clean solution would only use a void pointer interimswise. It could look like this:
int main(int argc, char* argv[])
{
thread_func_param* thread_result;
...
...
pthread_create(&threadID[i], &attributes, fibGen, argv[i+1]);
{
void * pv;
pthread_join(threadID[i], &pv);
thread_result = pv;
}
if (NULL != thread_result) /* perform some sanity checking. */
{
for (j = 0; j < thread_result->size - 1; j++)
printf(" %d ", thread_result->fib[j]);
}
...
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 4 years ago.
I have created a structure which includes an array of strings and have populated that with words. When I try and fill the array more than half full I want to create a larger structure, copy the current data to that larger structure and then have that larger structure 'replace' the old one that is called from main. Although I have successfully created and copied the data to the new structure; which I can prove by printing the data out from within the function; I am not able to replace the old structure in main. The next book_insert I try inserts to the old, smaller structure not the new, larger one.
I am operating within a constraint whereby I cannot do the resizing / copying / replacing within main; it has to be called from the book_insert function called from main. Additionally I cannot edit void book_insert(dic* s, char* v) (i.e. add double pointers), it has to remain in this format.
#include <stdio.h>
#include <stdlib.h>
struct book {
int size;
int count;
char** words;
};
typedef struct book book;
/* Create empty book, specifying lenght of strings and how many of them */
book* book_init(int wordlen, int maxwords);
/* Add one element into the book */
void book_insert(book* s, char* v);
/* Creates and returns new, bigger book */
book* resize(book* s, book* new);
/* Prints book */
void prints(book* a);
int main(void)
{
book* test;
test = book_init(60, 10);
book_insert(test, "dog");
book_insert(test, "cat");
book_insert(test, "mouse");
book_insert(test, "elephant");
book_insert(test, "snake");
/*The next insert will cause the resize function to trigger*/
book_insert(test, "fish");
/*The resize funtion should cause 'test' to be replaced by a bigger book*/
/*But doesn't as this next print shows*/
printf("But printing from main function means I'm back to %d\n", test->size);
prints(test);
}
void book_insert(book* s, char* v)
{
int i = 0;
while (s->words[i] != NULL ) {
i++;
}
s->words[i] = v;
s->count++;
/*If the book is half full resize is triggered, and should pass back new, bigger book*/
if((s->count * 100 / s->size) > 50) {
book *new_book;
new_book = book_init(60, 20);
s = resize(s, new_book);
printf("Printing from resize function gives me new length of %d\n", s->size);
prints(s);
}
}
book* resize(book* s, book* new)
{
int i;
for (i = 0; i < s->size; i++) {
if (s->words[i] != NULL ) {
new->words[i] = s->words[i];
}
}
return new;
}
book* book_init(int wordlen, int maxwords)
{
int i;
book* new = malloc(sizeof(book));
new->size = maxwords;
new->count = 0;
new->words = (char**) calloc((size_t)new->size, sizeof(char*));
for (i=0; i<new->size; i++) {
new->words[i] = (char*) calloc(wordlen, sizeof(char));
new->words[i] = NULL;
}
return new;
}
void prints(book* a)
{
int i;
for (i = 0; i < a->size; i++) {
printf("Index: %d, word: %s\n", i, a->words[i]);
}
}
I have also attempted this with a pointer swap in a separate function, but this does not seem to work either. In this version I have made book_resize void and instead from dic_insert called the below function, after the resize, with dictionary_swap(&new_book, &s):
void dictionary_swap(book **new, book **old)
{
book *temp = *old;
*old = *new;
*new = temp;
}
This again lets me print out the new larger, structure within the book_insert function, but has no affect on what happens in main.
EDIT ANSWER
This question has been marked as a duplicate, which means I can't answer it myself, however I have since found the answer; I changed the above duplicate swap so that I called dictionary_swap(new_book, s); (no ampersands) on the following code:
void dictionary_swap(book *new, book *old)
{
book temp;
temp = *old;
*old = *new;
*new = temp;
}
In order to modify a pointer inside a function you have to pass the address of the pointer to the function, eg:
void changePtr(char* test) {
test = "Hello";
}
The above will not work because test cannot be returned to the caller, however:
void changePtr(char** test) {
if ( test != NULL ) {
*test = "Hello";
}
}
The above will work because the address of the pointer is passed and it can be de-referenced to change the contents.
Example of calling:
char* ptr;
changePtr(&ptr);
Here is a rewrite of your code implementing the above technique:
#include <stdio.h>
#include <stdlib.h>
typedef struct _book {
int size;
int count;
char** words; //Must allocate space for each pointer before copying to.
} book;
//No need for below, see above:
//typedef struct book book;
/* Create empty book, specifying lenght of strings and how many of them */
book* book_init(int wordlen, int maxwords);
/* Add one element into the book */
void book_insert(book** s, char* v);
/* Creates and returns new, bigger book */
book* resize(book* s, book* new);
/* Prints book */
void prints(book* a);
int main(void) {
book* test = book_init(60, 10);
book_insert(&test, "dog");
book_insert(&test, "cat");
book_insert(&test, "mouse");
book_insert(&test, "elephant");
book_insert(&test, "snake");
/*The next insert will cause the resize function to trigger*/
book_insert(&test, "fish");
/*The resize funtion should cause 'test' to be replaced by a bigger book*/
/*But doesn't as this next print shows*/
printf("But printing from main function means I'm back to %d\n", test->size);
prints(test);
}
void book_insert(book** s, char* v) {
if ( s == NULL || v == NULL ) {
return;
}
(*s)->words = realloc((*s)->words, sizeof(char*) * (++(*s)->count));
(*s)->words[(*s)->count - 1] = v;
/*If the book is half full resize is triggered, and should pass back new, bigger book*/
if((((*s)->count * 100) / s->size) > 50) {
book *new_book;
new_book = book_init(60, 20);
*s = resize(*s, new_book);
}
}
book* resize(book* s, book* new) {
int i;
for (i = 0; i < s->size; i++) {
if (s->words[i] != NULL ) {
new->words[i] = s->words[i];
}
}
printf("Printing from resize function gives me new length of %d\n", new->size);
prints(new);
return new;
}
book* book_init(int wordlen, int maxwords) {
int i;
book* new = calloc(1, sizeof(book));
new->size = maxwords;
return new;
}
void prints(book* a) {
int i;
for (i = 0; i < a->size; i++) {
printf("Index: %d, word: %s\n", i, a->words[i]);
}
}
In C I try to learn queue data structure and make pointer to struct but inside the struct there is pointer to array. Here queue is struct, q is pointer to the struct, and inside struct there are rear, front, num and int *que(pointer to array to store data)
typedef struct {
int max;
int rear;
int front;
int num;
int *que;
} queue;
And malloc() using
queue->que=malloc(sizeof(int)12) ; to make arrray And to access it,
q->que[q->rear++] //not to familiar,
First I'm not declaring array but can I access data pointed by que using []?
Is this mean access que[q->rear++] inside q pointer?
Is this the same as (q).que[q->rear++]? I got segmentation fault .
Part of the code; but there are some errors
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int max;
int num;
int front;
int rear;
int *que;
} queue;
int initialization(queue*q, int max) {
q->num = 0;
q->front = 0;
q->rear = 0;
if (q->que =(int*)malloc(max * sizeof(int)) == NULL) { // got pointer NULL i dont know why
q->max = 0;
return-1;
}
q->max=max;
return 0;
}
int main() {
queue que;
if (initialization(&que, 12) == -1)
printf("fail");
else {
int m,x;
while (m != 0) {
printf("1.enque 2.deque. 3.peek 4.display 0. slese");
scanf("%d", &m);
switch (m) {
case 0: break;
case 1: printf("data");
scanf("%d", &x);
enqueue(&que, x);
break;
case 2: dequeue(&que, &x);
printf("%d is dequeue", x);
break;
case 3:x=peek(&que,&x);
printf("max now is %d", x);
break;
case 4:display(&que);
}
}
}
int enqueue(queue*q, int x) {
if (q->num >= q->max)
return -1;
else{
q->num++;
q->que[q->rear++]= x; //got segmentation fault
if (q->rear == q->max)
q->rear = 0;
}
}
In your initialization() function, while allocation memory with malloc() like
if (q->que =(int*)malloc(max * sizeof(int)) == NULL) {
the (int*)malloc(max * sizeof(int)) part is evaluated first and then this value is compared against NULL via the == operator. This will result in 0 if the condition is false and 1 otherwise.
Now this (0 or 1) value is being assigned to q->que instead of the return value of malloc(). So bottom-line is that q->que points to the memory location 0 (or 1 as the case maybe) which is most probably not a part of memory that a normal program is allowed to mess with and hence you get error.
You can solve this operator precedence problem by using parenthesis like
if ((q->que = malloc(max * sizeof(int))) == NULL) {
And in your while loop inside main(), the control expression is m!=0 but m is not even initialised during the first iteration. At that point, its value is indeterminate (garbage value).
You could initialise m to something other than 0 first like
int m=1,x;
while (m != 0) {
And in C, you needn't cast the value returned by malloc(). See here.
I have searched quite a bit, before asking, but I can't seem to make this function work.
I have this array of structs with 2 strings (char*)
and the function put() that adds a new struct, Unless the key already exists in that case it just ovewrites the current value with the new one.
Despite I am passing the array by reference and not making a local copy in the function, the memory still is corrupted (Segmentation Fault).
The source code is compiled under Ubuntu 15.10 on latest version of gcc.
Thanks in advance for your help guys!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 3
struct store{
char *key;
char *value;
};
void put(char *key, char *value, struct store **store, int size){
int i, found;
struct store *temp = realloc(*store, (size + 1) * sizeof(struct store));
for(i = 0; i < size; ++i){
if(strcmp(key, store[i]->key) == 0){ //Key found, overwrite new value.
store[i]->value = strdup(value); //Assume that every value is null terminated
found = 1;
break;
}
}
if(found) return;
*store = temp;
if(!store){
perror("realloc failed");
exit(EXIT_FAILURE);
}
store[size]->key = strdup(key); //New element
store[size]->value = strdup(value);
return;
}
int main(){
int i = 0;
struct store *store = malloc(N * sizeof(struct store));
if(!store){
perror("malloc failed");
exit(EXIT_FAILURE);
}
store[0].key = strdup("123a");
store[1].key = strdup("456b");
store[2].key = strdup("789c");
store[0].value = strdup("John");
store[1].value = strdup("Sam");
store[2].value = strdup("Mary");
for(i = 0; i < N; ++i)
printf("%s, %s\n\n",store[i].key,store[i].value); //This works fine
put("123a","Jim",&store,N);
for(i = 0; i < N; ++i)
printf("%s, %s\n\n",store[i].key,store[i].value);
put("653a","Tom",&store,N);
for(i = 0; i < N+1; ++i)
printf("%s, %s\n\n",store[i].key,store[i].value);
return 0;
}
struct store *temp = realloc(*store, (size + 1) * sizeof(struct store));
for(i = 0; i < size; ++i){
if(strcmp(key, store[i]->key) == 0){ //Key found, overwrite new value.
store[i]->value = strdup(value); //Assume that every value is null terminated
found = 1;
break;
}
}
if(found) return;
*store = temp;
If the key is found, you don't assign temp to *store. realloc can move the allocated memory to a completely new address, thus leaving *store a dangling pointer. And you really should also check that temp isn't null as well.
There's also the problem of your misuse of store. store is the the address of the pointer you passed into the function, not the first element of an array.
You need to index the array like this (*store)[i].
I know there are a lot of double pointer questions, but I couldn't find one that pertained to starting an array.
In the code below, I can set pointers in main by ptrs[0] = &array[0];, but the code halts when enqueue() calls *queue[i] = p;. Why is that? I don't know if it matters, but ptrs[] is not initialized.
#define QUEUE_LEN 5
int *ptrs[5];
int array[5] = {1,2,3,4,5};
void enqueue(int *p, int **queue) {
int i = 0;
int *tmp;
// Find correct slot
while (*queue && *queue[i] >= *p) {
i++;
}
// Error no free slots
if (i == QUEUE_LEN) {
printf("No free slots.\r\n");
return;
}
// Insert process
if (!*queue) {
*queue[i] = p;
return;
}
else {
tmp = *queue[i];
*queue[i] = p;
}
// Increment the other processes
return;
}
int main(int argc, char** argv) {
int i;
for (i=0; i<5; i++) {
enqueue(&array[i], ptrs);
}
for (i=0; i<QUEUE_LEN; i++)
printf("%d\n", *(ptrs[i]));
return 0;
}
After first loop, i will remain zero. Here:
if (!*queue) {
*queue[i] = p;
return;
}
You check, that *queue is 0 and dereference it as well. It is UB.
PS. Btw, this:
*queue[i] = p;
Will not compiles, since *queue[i] has type int, but p has type int*.
// Find correct slot
while (*queue && *queue[i] >= *p) {
i++;
}
This will access some random memory address taken from uninitialized ptrs value.
Your check for *queue != 0 is not enough, you need to initialize array with zeores as:
int *ptrs[5] = {0};
And you still need to allocate memory you are attempting to write later when inserting.