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.
Related
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.
This code has a problem in the struct data members. When I call a function like Evaluator() function the token[0].value will corrupt or will turn into a garbage. I tried to allocate a memory for the value data member but still no luck. I also tried to allocate a memory for the struct itself but still it doesn't work. Can someone help me with this?
struct tokens
{
char *value;
char type = ' ';
};
void inputComponent(char input_string[size])
printf("\n> ");
scanf("%[^\n]s", input_string);
}
int processingComponent(char *input_string, int *result)
{
int error_flag = 0;
tokens token[size];
error_flag = Parser(input_string, token);
if (error_flag == 0)
error_flag = Evaluator(result, token);
return error_flag;
}
int Parser(char *input_string, struct tokens token[size])
{
char valid_operators[size] = { "+-*/%" };
char temp = ' ';
char number_string[size] = { NULL };
int counter = 0;
int countStruct = 0;
int tempCounter = 0;
do
{
temp = input_string[counter];
if (isdigit(temp))
{
number_string[tempCounter] = temp;
tempCounter++;
}
else if (strpbrk(input_string, valid_operators))
{
if (temp == '%')
return (-1);
else if (number_string != NULL)
{
char tempNum[size] = { NULL };
strcpy(tempNum, number_string);
token[countStruct].value = tempNum;
token[countStruct].type = 'N';
countStruct++;
tempCounter = 0;
for (int x = 0; number_string[x] != NULL; x++)
number_string[x] = NULL;
}
}
else
return (-2);
counter++;
} while (counter < strlen(input_string));
return 0;
}
int Evaluator(int *result, struct tokens token[size])
{
for(int x = 0; x < 3; x++) //value of token[0].value = ÌÌÌÌÌÌÌÌÌÌÌÌ
printf("%s", token[x].value);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
char input_string[size] = { NULL };
int result = 0;
int error_flag = 0;
inputComponent(input_string);
error_flag = processingComponent(input_string, &result);
_getch();
_getch();
return 0;
}
For starters, when you pass an array of tokens to the Parser and Evaluator functions, you are passing the variables by value. The token array is not actually changed after calling Parser():
`
int Parser(char *input_string, struct tokens myArray[size])
{
//modifying myArray will not modify the array that was actually passed
//to this function from the processingComponent() function.
}
`
First change your Parser and Evaluator functions like so:
#define ARRAY_SIZE 100 //an arbitrary size
int Parser( char* input_string, struct token* tokenArray )
{
//access each element as so:
//tokenArray[0];
//tokenArray[ ARRAY_SIZE - 1 ];
}
int Evaluator(int *result, struct token* tokenArray )
{
for(int x = 0; x < ARRAY_SIZE; x++)
printf("%s", tokenArray[x].value);
return 0;
}
Then call the Parser() function as so:
EDIT: Since it is a good idea to allocate and free memory within the same function (so that you don't end up with spaghetti code), this would be a better solution:
int processingComponent(char *input_string, int *result)
{
int error_flag = 0;
token tokenArray[ARRAY_SIZE];
//allocate memory here
for( int i = 0; i < ARRAY_SIZE; i++ ) {
tokenArray[i].value = (char*)malloc( sizeof(char) * MAX_STRING_LENGTH);
}
error_flag = Parser(input_string, &tokenArray[0]);
if (error_flag == 0)
error_flag = Evaluator(result, &tokenArray[0]);
//free memory here before the token array goes out of scope:
for( int i = 0; i < ARRAY_SIZE; i++ ) {
free( tokenArray[i].value );
tokenArray[i].value = NULL;
}
return error_flag;
}
When you allocate memory for your token string, it needs to be dynamically allocated using malloc() and deleted using free().
Replace this:
strcpy(tempNum, number_string);
token[countStruct].value = tempNum;
//with:
#define MAX_STRING_LENGTH 255 //arbitrary
//Memory has already been allocated, so just copy the string into the token
strncpy( token[countStruct].value, number_string, MAX_STRING_LENGTH - 1 );
token[countStruct].value[MAX_STRING_LENGTH-1] = NULL;
You don't appear to be allocating any storage for token[].value. You set it equal to tempNum, but that goes out of scope in the inner block in Parser(). I would say that anything this code does is undefined because you're accessing memory that was deallocated when Parser() returned.
Precautions with Structures
I have added a text file, which contains your running code with instructions.
one important thing you can not assign any thing directly into structure, because declaration of structure reserve no space.
Why did you do such a hectic job to achieve something like this..
input :12+3-1/7
output:12317
Click this link to get your running c code
I was playing with double pointers in C and was wondering if I create a function that initializes the table, it crashes on going back to main when I try to make use of the memory allocated by InitStringTable. I believe a simple fix is to make strTable global and then I believe its OK, but I prefer not to do so as this is more of a learning exercise for me in passing the table around for modification i.e. I should be able to modify strTable from main or another function modifyTable after InitStringTable.
Thanks for any help you can give.
int main()
{
char** strTable;
// Allocates memory for string table.
InitStringTable(strTable);
// Below lines should be able to copy strings into newly allocated table.
// Below lines cause crash however.
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
// Allocates memory for the string table. This function should create a table
// of size 10 strings with each string 50 chars long. The code compiles fine.
void InitStringTable(char** table)
{
int i = 0;
table = (char**)malloc(sizeof(char)*10);
for(i = 0; i < 10; i++)
{
table[i] = (char*)malloc(sizeof(char)*50);
}
for(i = 0; i < 10; i++)
{
memset(table[i], 0, 50);
}
strcpy(table[0], "string1");
}
C is pass by value.
The value assigned to table is lost on returning from InitStringTable().
Also when allocating pointers to char ask for room for pointers to char.
So this:
... = (char**)malloc(sizeof(char)*10);
shall at least be (assuming C):
... = malloc(sizeof(char*)*10);
A possible approach to this would be:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int InitStringTable(char *** ppptable, const size_t n, const size_t l)
{
int result = 0;
if (NULL == ppptable)
{
result = -1;
errno = EINVAL;
}
else
{
(*ppptable) = malloc(n * sizeof(**ppptable));
if (NULL == (*ppptable))
{
result = -1;
}
else
{
size_t i = 0;
for(; i < n; ++i)
{
(*ppptable)[i] = calloc(l, sizeof(*(*ppptable)[i]));
if (NULL == (*ppptable)[i])
{
result = -1;
/* Failing in the middle requires clean-up. */
for (; i > 0; --i)
{
free((*ppptable)[i-1]);
}
free(*ppptable);
(*ppptable) = NULL;
break;
}
}
}
}
return result;
}
Call it like this:
#include <stdlib.h>
#include <stdio.h>
int InitStringTable(char *** ppptable, const size_t n, const size_t l);
int main(void)
{
int result = EXIT_SUCCESS;
char ** strTable = NULL;
if ( -1 == InitStringTable(&strTable, 10, 42)) //* Allocate array with 10 "strings" à 42 chars. */
{
perror("InitStringTable() failed");
result = EXIT_FAILURE;
}
else
{
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
return result;
}
And no, I won't get into this ridiculous "You don't wanna be a 3-star-programmer!" discussion.
You have a pointer issue.
It's like if you say:
void inc(int a){
a++;
}
int main(){
int a = 0;
inc(a);
printf ("%d\n", a); // will display 0, not 1
}
does not work.
You must pass &strTable instead of strTable as InitStringTable argument, and change other things in InitStringTable consequently ..
Or just do strTable = InitStringTable(); , and return a char** from InitStringTable.
The lines below InitStringTable() crash, because they are trying to perform operations
on a memory address that is neither in the same scope as theirs nor have any reference to
that memory address.
The function InitStringTable() allocates memory to the table, but cannot be accessed by the
calling function (here main), because the memory is local to the function in which it
allocated.
Therefore in order to use the same memory address for operations in the
calling function you must pass a reference of that address to the calling function.
In your program you can do it as under :
Declare the function as :-
char **InitStringTable(char **);
int main()
{
char** strTable;
strTable = InitStringTable(strTable);
strcpy(strTable[0], "abcdef");
strcpy(strTable[1], "xy");
}
char **InitStringTable(char** table)
{
int i = 0;
table = (char**)malloc(sizeof(char)*10);
for(i = 0; i < 10; i++)
{
table[i] = (char*)malloc(sizeof(char)*50);
}
for(i = 0; i < 10; i++)
{
memset(table[i], 0, 50);
}
strcpy(table[0], "string1");
/* after the function has finished its job, return the address of the table */
return table;
}
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.
I have declared the following struct:
typedef struct _RECOGNITIONRESULT {
int begin_time_ms, end_time_ms;
char* word;
} RECOGNITIONRESULT;
There is a method that creates an array of RECOGNITIONRESULT and fills it (for test purposes only):
void test_realloc(RECOGNITIONRESULT** p, int count){
int i;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
for (i = 0; i < count; i++){
(*p)[i].begin_time_ms = 2*i;
(*p)[i].end_time_ms = 2*i+1;
(*p)[i].word=(char *) malloc ( (strlen("hello"+1) * sizeof(char ) ));
strcpy((*p)[i].word,"hello");
}
}
The method to free memory is:
void free_realloc(RECOGNITIONRESULT* p, int count){
int i = 0;
if(p != NULL){
if (count > 0){
for (i = 0; i < count; i++){
free(p[i].word); //THE PROBLEM IS HERE.
}
}
free(p);
}
}
The main method calls those methods like this:
int main(int argc, char** argv)
{
int count = 10;
RECOGNITIONRESULT *p = NULL;
test_realloc(&p,count);
free_realloc(p,count);
return 0;
}
Then if I try to free the memory allocated for "word", I get the following error:
HEAP CORRUPTION DETECTED: after normal block (#63) at 0x003D31D8.
CRT detected that the application wrote to memory after end of heap buffer.
Using the debugger I've discovered that the crash occurs when calling free(p[i].word);
What am I doing wrong? How can I free he memory for the strings?
The problem is in your allocation of memory for word. strlen("hello"+1) should be strlen("hello")+1.
Since you appear to allocate a whole array of structures in one strike
RECOGNITIONRESULT **p;
*p = (RECOGNITIONRESULT *)realloc(*p, count * sizeof(RECOGNITIONRESULT));
you can free them in one call to free() as well :
void free_realloc(RECOGNITIONRESULT *p, int count){
free(p);
}
And the strlen("hello"+1) is also wrong, as detected by Chowlett.