Data saved in Stack content keep changing, can't increment - c

So here is my issue, I have been trying to figure this out for the last 5 hours, I have a header file, a tester file, and a c source file. I would really like to understand what is happening and why so I can avoid the issue in the future. The header file declares the struct but does not define it:
typedef struct Stack *StackP;
and in my source file, Stack.c I have defined the stack:
struct Stack
{
int top;
int capacity;
int count;
ItemT items;
};
where ItemT is defined as char *
in the tester file, the call goes:
StackP stackPtr = newStack();
and what I have for my newStack function located in the c source file is:
StackP newStack(void) {
struct Stack stack1;
StackP stackPtr = &stack1;
(stackPtr->items) = (ItemT)malloc(DEFAULT_CAPACITY*sizeof(ItemT));
(stackPtr->top) = -1;
(stackPtr->capacity) = DEFAULT_CAPACITY;
(stackPtr->count) = 0;
fprintf(stderr, "\nSuccesfully allocated memory to items...\n");
return stackPtr;
}
now, my push function is:
void pushStack(StackP stackPtr, ItemT item) {
if ((stackPtr->count) == (stackPtr->capacity)) {
fprintf(stderr, "\nERROR: Full stack.\n");
}
else {
stackPtr->items = item;
fprintf(stderr, "\nSuccessfully pushed %s on to the stack...\n", stackPtr->items);
(stackPtr->items)++;
(stackPtr->top)++;
(stackPtr->count)++;
}
}
My question is this: Have I don't something wrong in any of these blocks of code.
If I call a function that says:
return (stackPtr->count);
it will return a random set of numbers instead of 0, or 1. For instance, if I push 2 strings to the stack, instead of count being 2, count is 479622 or some other random long number. Why is this happening?
Again, I would like to know what I'm doing wrong and not just correct syntax because I really HAVE to understand this.

The program has undefined behaviour as it is returning the address of a local variable from a function:
StackP newStack(void) {
struct Stack stack1;
StackP stackPtr = &stack1;
return stackPtr;
}
stack1 no longer exists when newStack exits. stackPtr must point to dynamically allocated memory if it is to exist beyond the scope of the function:
StackP newStack(void) {
struct Stack stack1;
StackP stackPtr = malloc(sizeof(*stackPtr));
if (stackPtr)
{
}
return stackPtr;
}
See Do I cast the result of malloc?

Related

Deleting resources

I'm a beginner in C. I currently have a task to create a program having multiple queues. How should i correct this? From my understanding, is supposed to clear all of the queues that where created. As currently i think i have memory leaks.
#include <stdio.h> //printf etc
#include <stdlib.h> //malloc calloc realloc free
#include <stdint.h>
/* number of message queues */
#define MSGQS_LEN 5
/* number of nodes in the message queue */
#define CAPACITY 5
typedef struct _node {
const char* message;
struct _node* next;
} node_t;
typedef struct {
char qName;
node_t *front, *rear;
} msg_queue_t;
typedef struct {
msg_queue_t **queues;
} MsgQs_t;
Your code has several problems.
if(msg_queues < 0)
exit(EXIT_FAILURE);
This test is not correct, msg_queues will be NULL if malloc failed for some reason, the test should read.
if(msg_queues == NULL)
exit(EXIT_FAILURE);
/* Relinquishes all resources currently held by a MsgQs_t.
The pointer to the MsgQs_t in question is set to NULL. */
MsgQs_t* unloadMsgQs(){
MsgQs_t *msg_queues;
msg_queues = NULL;
return(msg_queues);
}
You allocate a variable on the stack, initialize it to NULL and return NULL from this function.
What you actually want to do is pass a MsqQs_t* to unloadMsgQs and use this pointer as an argument to free, something like this
void unloadMsgQs(MsgQs_t *msg_q) {
if(msg_q) {
free(msg_q);
}
}
If you want to set the msg_q pointer to NULL so that it can't be reused anymore, you should probably do something like.
void unloadMsgQs(MsgQs_t **msg_q) {
if(msg_q && *msg_q) {
free(*msg_q);
*msg_q = NULL;
}
}
From what I see, my advice would be to read some more books / tutorials on programming with C and pointers in general, because it seems you don't quite grasp the basics yet (which is nothing to be ashamed of of course!)
You have to call free with the pointer value returned from malloc. For this you have to pass the pointer to unloadMsgQs as an argument.
If this function is supposed to set the pointer to NULL in the caller, you have to pass the address of the pointer.
Note that malloc's return value to indicate an error is NULL not a value < 0.
/* Returns a pointer to MsgQs_t structure and through which multiple message queues can be subsequently created.
Each individual message queue is to be identified by a unique identifier. */
MsgQs_t* initializeMsgQs(){
MsgQs_t* msg_queues;
msg_queues = malloc(sizeof(MsgQs_t));
if(msg_queues == NULL)
exit(EXIT_FAILURE);
return(msg_queues);
}
/* Relinquishes all resources currently held by a MsgQs_t.
The pointer to the MsgQs_t in question is set to NULL. */
void unloadMsgQs(MsgQs_t **msg_queues){
if(msg_queues != NULL)
{
free(*msg_queues);
*msg_queues = NULL;
}
}
/* sample use in main() */
int main(int argc, char **argv)
{
MsgQs_t* msg_queues;
msg_queues = initializeMsgQs();
/* ... */
unloadMsgQs(&msg_queues);
return 0;
}

Bad memory access while calling function

Actually i developing using unit test.
But i break down my code in other form to ask for the error that i faced.
I have these declaration in my header file
typedef struct
{
void *topOfStack;
}Stack;
typedef enum {NUMBER,OPERATOR,IDENTIFIER}Token;
int operatorEvaluate(Stack *numberStack , Stack *operatorStack);
void * pop(Stack *stack);
The following is the respective source file
#include "try.h"
void *pop(Stack *numberStack)
{
Token *newToken = NUMBER;
return newToken;
}
int operatorEvaluate(Stack *numberStack , Stack *operatorStack)
{
Token *first = (Token*)pop (numberStack);
if(numberStack != operatorStack)
{
if(*first == NUMBER)
return 1;
}
return 0;
}
This is the source file that i call the functions which is main
#include "try.h"
#include <stdio.h>
int main ()
{
Stack numberStack;
Stack operatorStack;
int num;
num = operatorEvaluate(&numberStack , &operatorStack);
printf("This is the returned value: %d",num);
return 0;
}
When i tried to compile, the unit test tell me that bad memory access.
So i try to use eclipse to compile these, and windows tells that the .exe had stop working.
Hope someone can help me, i stuck for a long time...
Enable compiler warnings.
In particular, this makes zero sense:
Token *newToken = NUMBER;
That's a pointer, and you're assigning a value.
I cannot propose a fix, as I have no idea what you're doing.
That pop() function isn't touching the stack, and is returning an enum converted to a pointer. If you try to access anything through that pointer, it's going to provoke undefined behavior.
Your pop function is wrong in a few ways. You probably want it to actually pop your stack, rather than return a constant (which it isn't doing either, by the way!)...something like this:
void *pop(Stack *numberStack)
{
return numberStack->topOfStack;
}
but if you do that it'll still crash, because you never initialize your stack OR fill the topOfStack pointer.

Malloc Typedef Struct Problems

I am working on building a threads library and for some reason have run into a simple malloc problem that I can't fix right now. I'm sure it's something simple I'm just missing it.
In my main.c I have the following code:
//declare testSem
tasem_t testSem;
int main(int argc, char **argv){
ta_libinit();
//initialize testSem
ta_sem_init(&testSem, 5);
//wait test
ta_sem_wait(&testSem);
the relevant code in my thread library is as follows:
void ta_sem_init(tasem_t *sema, int value)
{
//malloc the semaphore struct
sema = malloc(sizeof(tasem_t));
//error check
if(sema == NULL)
{
printf("could not malloc semaphore");
exit(0);
}
//initialize with the given value
sema->val = value;
printf("SemaVal = %i\n", sema->val);
}
void ta_sem_wait(tasem_t *sema)
{
printf("SemaVal = %i\n", sema->val);
if(sema->val <= 0)
{
//not done yet
printf("SWAPPING\n");
}
else
{
printf("SemaVal = %i\n", sema->val);
sema->val = sema->val + 1;
}
}
Here is the struct from my header file:
//struct to store each semas info
typedef struct tasem_t_struct
{
//value
int val;
//Q* Queue
//int numThreads
}tasem_t;
The output I get from this is:
SemaVal = 5
SemaVal = 0
SWAPPING
So evidently, I'm not mallocing my struct correctly as the value inside is lost once I go out of scope. I know I must just be forgetting something simple. Any ideas?
You can't seem to decide who's responsible for allocating your tasem_t structure. You have a global variable for it and pass its address to ta_sem_init. But then you have ta_sem_init dynamically allocate a brand new tasem_t structure, saving its address to sema, a local function argument, so that address gets lost when it falls out of scope.
Pick one, either:
Make ta_sem_init initialize an existing tasem_t variable.
Make ta_sem_init allocate and initialize a new tasem_t structure and then return its address (either directly or via a tasem_t** output parameter).

Setting struct variables - C

I have some code in the following kind of layout, I believe that the topExample/botExample aren't being set properly when I call addTopBotExample. I think this is due to the top bot variables being on the functions stack and so being cleared when the function ends? I have a feeling that perhaps I need to malloc the memory first, but am not sure how I would go about doing this are even if its the right approach.
typedef struct Example Example;
struct Example {
/* normal variables ...*/
Example *topExample;
Example *botExample;
};
....
void addTopBotExample(Example **example, int someVariable) {
Example top = createTopExample(int someVariable); //(createTopExample returns a
//type Example based on some input)
Example bot = createBotExample(int someVariable);
(*example)->topExample = &top;
(*example)->botExample = &bot;
return;
}
If createTopExample isn't allocating memory, this is going to cause problems the moment it's called more than once. Rewrite createTopExample and createBotExample to use malloc and return an Example*. Something like this:
Example* createTopExample(stuff)
{
Example *example = malloc(sizeof(Example));
// ... stuff you do
return example;
}
Then your addTopBotExample would look like this:
void addTopBotExample(Example **example, int someVariable) {
if ((*example)->topExample)
free((*example)->topExample)
if ((*example)->botExample)
free((*example)->botExample)
(*example)->topExample = createTopExample(int someVariable);
(*example)->botExample = createBotExample(int someVariable);
return;
}
Note that this addTopBotExample will free the allocated memory before calling malloc again but before your program ends, you need to call free on any lingering Examples that used this addTopBotExample function:
free(exampleInstanceThatWasPassedIntoAddTopBotExampleAtSomePoint.topExample);
free(exampleInstanceThatWasPassedIntoAddTopBotExampleAtSomePoint.botExample);
You have already everything together. Allocate the Example in createTopExample or createTopExample
Example *createTopExample(int someVariable)
{
Example *x = malloc(sizeof(Example));
/* initialize x */
return x;
}
and in addTopBotExample
void addTopBotExample(Example *example, int someVariable) {
Example *top = createTopExample(int someVariable); //(createTopExample returns a
//type Example based on some input)
Example *bot = createBotExample(int someVariable);
example->topExample = top;
example->botExample = bot;
return;
}
Ooooo, this is bad. The expression "Example top" in the addTopBotExample() function allocated that object on the stack. It'll be trashed after exiting from the function. (Same for "Example bot" on the following line.) Something like this will work better:
void addTopBotExample(Example **example, int someVariable) {
Example *top = createTopExample(someVariable); // NOTE THE *
Example *bot = createBotExample(someVariable); // NOTE THE *
(*example)->topExample = top; // NOT &top !!
(*example)->botExample = bot; // NOT &bot !!
return;
}
And you'll want to write createTopExample and createBotExample so they return pointers:
#include <stdlib.h> // For malloc!
Example *createTopExample(stuff) // Note *. It's returning a pointer.
{
Example *example = malloc(sizeof(Example)); // Allocate on the HEAP. Lives after this function call.
// Fill in the fields of example.
example->field1 = 25; // Note the "->": you're dereferencing a pointer.
example->title = "Example title";
return example;
}

External Functions and Parameter Size Limitation (C)

I am very much stuck in the following issue. Any help is very much appreciated!
Basically I have a program wich contains an array of structs and I am getting a segmentation error when I call an external function. The error only happens when I have more than 170 items on the array being passed.
Nothing on the function is processed. The program stops exactly when accessing the function.
Is there a limit for the size of the parameters that are passed to external functions?
Main.c
struct ratingObj {
int uid;
int mid;
double rating;
};
void *FunctionLib; /* Handle to shared lib file */
void (*Function)(); /* Pointer to loaded routine */
const char *dlError; /* Pointer to error string */
int main( int argc, char * argv[]){
// ... some code ...
asprintf(&query, "select mid, rating "
"from %s "
"where uid=%d "
"order by rand()", itable, uid);
if (mysql_query(conn2, query)) {
fprintf(stderr, "%s\n", mysql_error(conn2));
exit(1);
}
res2 = mysql_store_result(conn2);
int movieCount = mysql_num_rows(res2);
// withhold is a variable that defines a percentage of the entries
// to be used for calculations (generally 20%)
int listSize = round((movieCount * ((double)withhold/100)));
struct ratingObj moviesToRate[listSize];
int mvCount = 0;
int count =0;
while ((row2 = mysql_fetch_row(res2)) != NULL){
if(count<(movieCount-listSize)){
// adds to another table
}else{
moviesToRate[mvCount].uid = uid;
moviesToRate[mvCount].mid = atoi(row2[0]);
moviesToRate[mvCount].rating = 0.0;
mvCount++;
}
count++;
}
// ... more code ...
FunctionLib = dlopen("library.so", RTLD_LAZY);
dlError = dlerror();
if( dlError ) exit(1);
Function = dlsym( FunctionLib, "getResults");
dlError = dlerror();
(*Function)( moviesToRate, listSize );
// .. more code
}
library.c
struct ratingObj {
int uid;
int mid;
double rating;
};
typedef struct ratingObj ratingObj;
void getResults(struct ratingObj *moviesToRate, int listSize);
void getResults(struct ratingObj *moviesToRate, int listSize){
// ... more code
}
You are likely blowing up the stack. Move the array to outside of the function, i.e. from auto to static land.
Another option is that the // ... more code - array gets populated... part is corrupting the stack.
Edit 0:
After you posted more code - you are using C99 variable sized array on the stack - Bad IdeaTM. Think what happens when your data set grows to thousands, or millions, of records. Switch to dynamic memory allocation, see malloc(3).
You don't show us what listsize is, but I suppose it is a variable and not a constant.
What you are using are variable length arrays, VLA. These are a bit dangerous if they are too large since they usually allocated on the stack.
To work around that you can allocate such a beast dynamically
struct ratingObj (*movies)[listSize] = malloc(sizeof(*movies));
// ...
free(movies);
You'd then have in mind though that movies then is a pointer to array, so you have to reference with one * more than before.
Another, more classical C version would be
struct ratingObj * movies = malloc(sizeof(*movies)*listsize);
// ...
free(movies);

Resources