Pointers getting junk values outside of functions, but regular values inside them - c

Full disclosure: This is my first time doing any significant programming in C, and my first post on Stack Overflow.
I'm working on code that will eventually be used with Bison to implement a small subset of the Scheme/Racket language. All of this code is in a single C file. I have three structs: Binding, Lambda, and SymbolEntry. I'm not using the Lambda struct yet, it's just there for completeness. I also have a symbol table that holds symbol entries. printSymbolTable() does exactly what the name implies:
typedef struct
{
char* name;
char* value;
} Binding;
typedef struct
{
int numBindings;
Binding** bindings;
char* functionBody;
} Lambda;
typedef struct
{
Binding* binding;
Lambda* function;
} SymbolEntry;
SymbolEntry* symbolTable = NULL;
int numSymbols = 0;
void printSymbolTable()
{
if (symbolTable)
{
int i = 0;
for (i; i < numSymbols; i++)
{
printf("\tsymbolTable[%i]: %s = %s\n", i, symbolTable[i].binding->name, symbolTable[i].binding->value);
}
}
}
I'm currently trying to work out the logic for defining and looking up variables. The 2 relevant functions:
// Takes a name and an exprssion and stores the result in the symbol table
void defineVar(char* name, char* expr)
{
printf("\nSetting %s = %s\n", name, expr);
printf("Previous number of symbols: %i\n", numSymbols);
Binding props;
props.name = name;
props.value = expr;
SymbolEntry entry;
entry.binding = &props;
entry.function = NULL;
symbolTable = realloc(symbolTable, sizeof(SymbolEntry) * ++numSymbols);
if (!symbolTable)
{
printf("Memory allocation failed. Exiting.\n");
exit(1);
}
symbolTable[numSymbols - 1] = entry;
printf("New number of symbols: %i\n", numSymbols);
printf("defineVar result:\n");
printSymbolTable();
}
// Test storing and looking up at least 4 variables, including one that is undefined
void testVars()
{
printf("Variable tests\n");
defineVar("foo", "0");
printf("After returning from defineVar:\n");
printSymbolTable();
defineVar("bar", "20");
printf("After returning from defineVar:\n");
printSymbolTable();
}
main() calls testVars(). I get no warnings or errors when compiling, and the program executes successfully. However, this is the result:
Variable tests
Setting foo = 0
Previous number of symbols: 0
New number of symbols: 1
defineVar result:
symbolTable[0]: foo = 0
After returning from defineVar:
symbolTable[0]: 1�I��^H��H���PTI��# = �E
Setting bar = 20
Previous number of symbols: 1
New number of symbols: 2
defineVar result:
symbolTable[0]: bar = 20
symbolTable[1]: bar = 20
After returning from defineVar:
symbolTable[0]: 1�I��^H��H���PTI��# = �E
symbolTable[1]: 1�I��^H��H���PTI��# = �E���
Not only am I getting junk values when outside of the defineVar() function, but the call to define bar shows incorrect non-junk values as well. I'm not sure what I'm doing wrong, but I assume it's probably something with realloc(). However, a similar strategy worked when parsing a string into individual tokens, so that's what I was trying to emulate. What am I doing wrong?

Because it's pointing to variables (or variable — at least props, haven't read further) local to functions and the stack frame is discarded (and soon overwritten) after you return.

Related

Pointer to linkedlist randomly changing

For one of my school assignments I have to make my own stack library and a POSTFIX calculator.
The calculator has to make use of the stack library and do some calculations.
I am pushing two different numbers to my stack. Number 6 and 3. The header should point to the most recently added node (LIFO). So when 6 is added:
HEADER -> 6 -> NULL
When 3 is being added:
HEADER -> 3 -> 6 -> NULL
When I print the value of my header after adding '6' it's good. It's printing 6.
However, when I print the value of my header BEFORE adding '3' it's printing '3'. When it still should print 6.
So a summary of my problem:
When adding another node to my linkedlist, the header suddenly points to the newest node before even changing it.
You may understand me better with some code and debugging results.
Btw: Don't mind the typedefs, I don't like them. My teacher wants us to use it.
typedef struct stackObject* pStackObject_t;
typedef struct stackObject
{
void* obj;
pStackObject_t next;
} StackObject_t;
typedef struct stackMEta* pStackMeta_t;
typedef struct stackMEta
{
pStackObject_t stack;
size_t objsize;
int numelem; //number of elements
int handle; //welke stack
pStackMeta_t next;
} StackMeta_t;
int mystack_push(int handle, void* obj)
{
**DELETED NON RELATED CODE BASED ON FEEDBACK**
if (currentMeta->handle == handle)
{
pStackObject_t newObject = malloc(sizeof(StackObject_t));
newObject->obj = obj;
printf("%s%d\n", "Wanting to push int to stack: ", *(int*)obj);
//First node
if (currentMeta->stack == NULL)
{
currentMeta->stack = newObject;
currentMeta->stack->next = NULL;
printf("%s%d\n", " FIRST Curentmeta->stack pointing to ", *(int*)currentMeta->stack->obj);
return 0;
}
else
{
printf("%s%d\n", "NOT FIRST Currentmeta->stack pointing to ", *(int*)currentMeta->stack->obj);
newObject->next = currentMeta->stack;
currentMeta->stack = newObject;
printf("%s%d\n", "Currentmeta->stack ", *(int*)currentMeta->stack->obj);
printf("%s%d\n", "Currentmeta->stack->next ", *(int*)currentMeta->stack->next->obj);
printf("%s%d\n", "Succesful pushed int to stack: ", *(int*)currentMeta->stack->obj);
return 0;
}
}
return -1;
}
Terminal:
Created stack with handle: 1 and objsize 4 bytes
Wanting to push int to stack: 6
FIRST Curentmeta->stack pointing to 6
Wanting to push int to stack: 3
NOT FIRST Currentmeta->stack pointing to 3
Currentmeta->stack 3
Currentmeta->stack->next 3
Succesful pushed int to stack: 3
My unit tests are performing good with this code. My calculator does not, while it's the same function call.
I found out that it was working 50/50. Using the same input values in another program resulted in good things.
I changed the code to this:
pStackObject_t newObject = malloc(sizeof(StackObject_t));
newObject->obj = malloc(sizeof(currentMeta->objsize));
memcpy(newObject->obj, obj, currentMeta->objsize);
Now it's working fine. The previous code was somehow using the old values, while it was already out of scope. Thanks everyone for the help.

Why is my structure zeroed out even when I did not return a object?

Ive been dabbling in some c code and initialized a cat structure like so
typedef struct
{
int age;
char *name;
char *favoriteQuote;
} Cat;
I created two functions, one to initialize the cat object and one to zero out the memory that look like so
Cat initialize_cat_object(void)
{
Cat my_cat;
my_cat.age = 3;
my_cat.favorite_quote = "A day without laughter is a day wasted";
my_cat.name = "Chester";
return my_cat;
}
Cat destroy_cat_object(void)
{
Cat my_cat;
memset(&my_cat, 0, sizeof(my_cat));
//--forgot to return 'my_cat' here--
}
my main function looks like so
void main(void)
{
Cat my_cat;
my_cat = initialize_cat_object();
printf("Creating cat\n")
printf("Name: %s\nFavoriteQuote: %s\nAge: %d\n", my_cat.name,
my_cat.favorite_quote, my_cat.age);
my_cat = destroy_cat_obect();
printf("CAT DESTRUCTION\n");
printf("Name: %s\nFavoriteQuote: %s\nAge: %d\n", my_cat.name,
my_cat.favorite_quote, my_cat.age);
}
The output of the program was the expected output of
It wasn't until I went back to the source code that I noticed I had forgotten to return the Cat object who's memory was zeroed out, However the program still shows the expected output, but if I try to omit the return statement of the 'initialize_cat_object' function, the output of the data is corrupt
The only thing I can think of is that 'destroy_cat_object' returns the zeroed out memory, but how could this be?
destroy_cat_object doesn't have a return statement. C11 6.9.1p12 says:
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
It is however perfectly OK C-standard-wise to have a function with a return type but which doesn't have a return statement before the closing bracket. Calling such a function is also perfectly OK.
What is not OK however is using the return value of the function call if the function didn't terminate with a return statement that explicitly returns a value.
You might want to enable some extra diagnostics in your compiler settings if you do not get a message for this.
Registers aside. There are three places where your data may be stored in C:
Constant data which is read only and is stored inside your binary;
Data on the stack;
Data stored in dynamic memory retrieved by the means of memory allocation functions.
In your case we are talking about stack. Stack is a LIFO queue elements of which are valid and accessible so long as they are not popped out of it. So if you have a function like this:
typedef struct {
int a_val;
float b_val;
char c_val;
} a_t;
a_t* func(void) {
a_t a = {1, 1., 'a'};
return &a;
}
"a" would be residing in stack until func returns, hence after func returns it's pointer becomes invalid and points someplace in stackspace. On the most systems stack won't be zeroed therefore until some other data overwrites it it may be possible to get some data by that pointer, which may be misleading.
So what should you do? Something like this:
void initialize_cat(Cat*);
void clear_cat(Cat*);
int main() {
Cat my_cat;
initialize_cat(&my_cat);
// do kitty stuff
clear_cat(&my_cat); // cat's private data must not be compromised
}
When function returns a structure this is actually achieved with a cooperation from a caller (I'm talking SysV x64 ABI here and may be wrong for other cases). Basically caller allocates space on stack enough to store the returned structure and passes pointer to it as an implicit first parameter. callee is using this pointer to write data later on.
So the two cases:
Cat callee(void) {
Cat my_cat = { .age = 5 };
return cat;
}
void caller(void) {
Cat my_cat = callee();
}
And:
void callee(Cat *my_cat) {
my_cat->age = 5;
return cat;
}
void caller(void) {
Cat my_cat;
callee(&my_cat);
}
Are pretty much the same.

C - Change variables values from a structure in a void* function

I have an exercise to do for school in C where I can't change the content of the main function and the type and parameters of the two others functions. I have searched Google already but found no answers my problem that I did understand.
The goal is simply to display the content of the structure with printf but I have an erreur due to not knowing how to return the structure to the main function.
This is the code :
void *create_mage(t_character *perso)
{
if ((perso = malloc(sizeof(t_character))) == NULL)
exit(84);
perso->niveau = 1;
perso->pdv = 100;
perso->mana = 200;
perso->attaque = 40;
perso->defense = 3;
perso->crit_chance = 10;
perso->vitesse = 4;
return (perso);
}
void *create_warrior(t_character *perso)
{
if ((perso = malloc(sizeof(t_character))) == NULL)
exit(84);
perso->niveau = 1;
perso->pdv = 200;
perso->mana = 50;
perso->attaque = 10;
perso->defense = 8;
perso->crit_chance = 10;
perso->vitesse = 3;
return (perso);
}
int main()
{
t_character p_ava;
t_character p_thi;
p_ava = create_mage(&p_ava);
p_thi = create_warrior(&p_thi);
printf("def %d - atk %d - vit %d - crit %d\n", p_ava.defense,
p_thi.attaque, p_ava.vitesse, p_thi.crit_chance);
return (0);
}
This is the error I get when I compile my project :
gcc *.c -Wall -Wextra
create_class.c: In function ‘main’:
create_class.c:48:9: error: incompatible types when assigning to type ‘t_character {aka struct s_character}’ from type ‘void *’
p_ava = create_mage(&p_ava);
^
create_class.c:49:9: error: incompatible types when assigning to type ‘t_character {aka struct s_character}’ from type ‘void *’
p_thi = create_warrior(&p_thi);
^
I do not have a good concept of how structures work and did not found anything concerning returning structures from void* functions so if you have an answer or a link where I could find one to my problem it would be very welcomed. Thank you in advance !
If you cannot change main, you cannot compile your code -- period (see comment by J. Leffler, above). However, if "change" means you "cannot add to", then you are OK. Why?
All you really need to do is to declare a struct (or better simply declare a typedef of the required structure as t_character) outside of main, and then within main remove p_ava = and p_thi = and remove the calls to malloc in each of your functions and you are fine.
Why? When you declare your structures:
t_character p_ava;
t_character p_thi;
You have created storage for a type t_character for each variable. The compiler simply needs to know what that type is. So you define the t_character struct (or typdef) and your compiler will provide adequate storage for the variables, e.g.
typedef struct {
int niveau, pdv, mana, attaque, defense, crit_chance, vitesse;
} t_character;
When you pass the variables to your functions (e.g. create_mage(&p_ava);) you are passing the address of p_ava to your function. There is already adequate storage created for a t_character at that address. So all you need to do in your functions is validate that you have a valid address for your variable passed to the function, and then just fill the member values for the struct.
Putting those pieces together, you could (not 'change', but 'remove') and do the following:
#include <stdio.h>
#include <stdlib.h> /* for exit() */
typedef struct {
int niveau, pdv, mana, attaque, defense, crit_chance, vitesse;
} t_character;
void *create_mage (t_character *perso)
{
if (!perso) {
fprintf (stderr, "create_mage() error: invalid parameter.\n");
exit (84);
}
perso->niveau = 1;
perso->pdv = 100;
perso->mana = 200;
perso->attaque = 40;
perso->defense = 3;
perso->crit_chance = 10;
perso->vitesse = 4;
return (perso);
}
void *create_warrior (t_character * perso)
{
if (!perso) {
fprintf (stderr, "create_warrior() error: invalid parameter.\n");
exit (84);
}
perso->niveau = 1;
perso->pdv = 200;
perso->mana = 50;
perso->attaque = 10;
perso->defense = 8;
perso->crit_chance = 10;
perso->vitesse = 3;
return (perso);
}
int main (void)
{
t_character p_ava;
t_character p_thi;
create_mage (&p_ava);
create_warrior (&p_thi);
printf ("def %d - atk %d - vit %d - crit %d\n", p_ava.defense,
p_thi.attaque, p_ava.vitesse, p_thi.crit_chance);
return 0;
}
note: you can get rid of the fprint statements and the test for the valid pointers as that 'change' was a matter of habit to validate function parameters, but is not necessary to the successful operation of the functions.
Compile
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/magewarrior magewarrior.c
Example Use/Output
$ ./bin/magewarrior
def 3 - atk 10 - vit 4 - crit 10
Look things over and let me know if you have any questions. If you cannot get away with remove, you are pretty much up a creek without a paddle...
Your alternative is to make p_ava and p_thi pointers as noted in the comments (replacing the '.' operator with the '->' arrow operator in your printf), then you can allocate with malloc within the functions, but will receive a warning for passing p_ava and p_thi uninitialized, unless the pointers are initialized NULL before calling:
p_ava = create_mage (p_ava);
This would require more change to main than the alternative, e.g.
int main (void)
{
t_character *p_ava = NULL;
t_character *p_thi = NULL;
p_ava = create_mage (p_ava);
p_thi = create_warrior (p_thi);
printf ("def %d - atk %d - vit %d - crit %d\n", p_ava->defense,
p_thi->attaque, p_ava->vitesse, p_thi->crit_chance);
return 0;
}
You will have to do one or the other.

Pointer to Pointer

I am having a lot of trouble with this piece of code (I am not good at pointers :P). So here is the code.
printf("\n Enter the file name along with its extensions that you want to delete:-");
scanf("%s",fileName);
deletefile_1_arg=fileName;
printf("test\n");
result_5 = deletefile_1(&deletefile_1_arg, clnt);
if (result_5 == (int *) NULL) {
clnt_perror (clnt, "call failed");
}
else
{
printf("\n File is deleted sucessfully");
goto Menu2;
}
break;
Function that is getting called is as following.
int *
deletefile_1_svc(char **argp, struct svc_req *rqstp)
{
static int result;
printf("test2\n");
printf("%s",**argp);
if(remove(**argp));
{
printf("\nFile Has Been Deleted");
result=1;
}
return &result;
}
I am getting test2 on console but. It does not print value of argp / removes that perticular file. I am not sure what I am doing wrong. Please help me.
The argp is a pointer to a pointer char, and you are trying to use it as a pointer to char, try change your code to:
printf("%s", *argp);
You would also need to change your remove call to:
remove(*argp);
I always found drawing pictures helped understand pointers. Use boxes for memory addresses and a label for the box is the variable name. If the variable is a pointer, then the contents of the box is the address of another box (draw line to the other box).
You are using pointers when you don't need to. Your "deletefile1_svc" function doesn't manipulate the value of "argp" at all so it doesn't need a pointer-to-pointer. Plus your "result" doesn't need to be returned as a pointer since it is simply a numeric value. You also don't initialize result (it might be zero) or re-initialize it (it is static so it will remember the last value assigned to it).
int
deletefile_1_svc(const char *argp, struct svc_req *rqstp)
{
int result = 0; /* Initial value => failure */
if (remove (argp) == 0)
{
result = 1; /* 1 => success */
}
return result;
}
To call the function use:
result_5 = deletefile1_svc(filename, clnt);
if (result_5 == 0)
// Failed
else
// Success
That will make the code simpler and less prone to bugs.

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