I have a variable struct employee which I initialized on the heap using malloc. I am passing this variable from a pointer using *tmp as shown bellow. The problem is that the values of the variable once passed to the function are wrong. I assume this has to do with the pointer but I can't find the mistake. I guess I am forgeting a basic about pointers. To me, I am passing the variable struct employee pointed by *tmp (and not its address as passing the pointer would do). Can't see what's wrong in there.
If I check the value inside the createEmployee() function or after calling it, they are right, but they are not in isInformationValid(employee e). If I change my code and pass a pointer to the function, everything works all right.
typedef struct employee{
char nom[MAX_NAME_LEN];
char prenom[MAX_NAME_LEN];
unsigned short badge;
unsigned long secret;
time_t lastAccess;
} employee;
typedef struct maillon maillon;
struct maillon{
maillon* next;
maillon* prev;
employee* e;
};
typedef struct e_list{
maillon* m;
} e_list;
[...]
int isInformationsValid(employee e){
int invalidName = (strlen(e.nom) <= 2 || strlen(e.prenom) <= 2); // Problem here
int invalidBadge = (e.badge < 1000 || e.badge > 9999); // Problem here. e.badge taken as "25789" when I input "1010"
if(invalidName) { errno = EPERM; perror("Name length must be > 2"); return -1; }
if(invalidBadge) { errno = EPERM; perror("Badge must be 4 digits"); return -1; }
return 0;
}
employee* createEmployee(){
employee* tmp = calloc(1, sizeof(employee*));
getString("A man needs a last name : ", tmp->nom, MAX_NAME_LEN);
getString("A man needs a first name : ", tmp->prenom, MAX_NAME_LEN);
getDigits("Badge (4 digit) : ", &tmp->badge, "%hu");
getDigits("Secret : ", &tmp->secret, "%lu");
time_t t = time(NULL);
tmp->lastAccess = t;
if(isInformationsValid(*tmp) == -1){ // Passing addr of the struct
return NULL;
}
return tmp;
}
What did I miss? Did I do something wrong in any initialization or am I missing a basic thing about pointers ?
I saw that other questions on stackoverflow has similar questions
The only answers I could reading those other questions was forgotten dynamic allocations on the heap, which is what I think I am doing (maybe the wrong way tho).
EDIT
I was doing it wrong.
You are allocating the size of an employee *, but you should be allocating the size of an employee (or *tmp).
Related
I'm wanting to pass a local variable within a function, back through it's pointer parameter (not returned).
My assignment uses a stack data structure, and one criteria that must be used is the Pop() function must have a pointer parameter that is used to return the top-most item on the stack. I have used this before. My program became more complex with a data struct, I started getting either segmentation faults, or the data not being saved after the function's frame popped.
// Definitions
typedef char * string;
typedef enum { SUCCESS, FAIL } result;
typedef enum { INTEGER, DOUBLE, STRING } item_tag;
// Result Check
static result RESULT;
// Item_Tag
typedef struct {
item_tag tag;
union {
int i;
double d;
string s;
} value;
} item;
// Declarations
int STACK_SIZE = 0;
const int MAX_STACK_SIZE = 1024; // Maximum stack size
item stack[1024];
// Pop
result Pop(item *ip){
item poppedItem;
item * pointerReturn = malloc(sizeof(item));
// Check stack size is not 0
if(STACK_SIZE == 0){
return FAIL;
}
// If stack size is only 1, creates a blank stack
else if(STACK_SIZE == 1){
item emptyItem;
// Initialize
emptyItem.tag = INTEGER;
emptyItem.value.i = 0;
// Check top item's tag
poppedItem = stack[0];
// Store top item data based on tag
switch(stack[0].tag){
case STRING:
poppedItem.value.s = stack[0].value.s;
case DOUBLE:
poppedItem.value.d = stack[0].value.d;
default:
poppedItem.value.i = stack[0].value.i;
}
poppedItem.tag = stack[0].tag;
// Allocate memory for parameter, and have it point to poppedItem
ip = malloc(sizeof(poppedItem));
*ip = poppedItem;
// Store empty stack to top of stack
stack[0] = emptyItem;
// Decrease stack size
STACK_SIZE--;
}
// Grab top Item from stack
else{
// Check top item's tag
poppedItem = stack[0];
// Store top item data based on tag
switch(stack[0].tag){
case STRING:
poppedItem.value.s = stack[0].value.s;
case DOUBLE:
poppedItem.value.d = stack[0].value.d;
default:
poppedItem.value.i = stack[0].value.i;
}
poppedItem.tag = stack[0].tag;
// Allocate memory for parameter, and have it point to poppedItem
ip = malloc(sizeof(poppedItem));
*ip = poppedItem;
// Reshuffle Items in Stack
for(int idx = 0; idx < STACK_SIZE; idx++){
stack[idx] = stack[idx + 1];
}
STACK_SIZE--;
}
return SUCCESS;
}
My knowledge with pointers is alright, and memory location/management. But I can't claim to be an expert by any means. I don't exactly know what happens in the background when you're using the function's own pointer parameter as a means of passing data back.
What is the correct syntax to solve this problem?
How can a parameter pass something back?
Thanks in advance!
EDIT*
Since many people are confused. I'll post some snippets. This is an assignment, so I cannot simply post all of it online as that'd be inappropriate. But I think it's okay to post the function itself and have people analyze it. I'm aware it's a bit messy atm since I've edited it several dozen times to try and figure out the solution. Sorry for the confusion. Keep in mind that not all the code is there. just the function in question, and some of the structure.
The function should receive a pointer to a valid object:
item catcher;
myFunc(&catcher); // Pass a pointer to catcher
and the function should modify the object it received a pointer to:
void myFunc(item *itemPointer)
{
itemPointer->variable = stuff;
// or
*itemPointer = someItem;
}
Update:
You're overcomplicating things immensely – there should be no mallocs when popping, and you're leaking memory all over the place.
(Your knowledge of pointers and memory management is far from "alright". It looks more like a novice's guesswork than knowledge.)
It should be something more like this:
result Pop(item *ip){
if (STACK_SIZE == 0){
return FAIL;
}
else {
*ip = stack[0];
for(int idx = 0; idx < STACK_SIZE; idx++){
stack[idx] = stack[idx + 1];
}
STACK_SIZE--;
}
return SUCCESS;
}
but it's better to push/pop at the far end of the array:
result Pop(item *ip){
if (STACK_SIZE == 0){
return FAIL;
}
else {
*ip = stack[STACK_SIZE-1];
STACK_SIZE--;
}
return SUCCESS;
}
Response to the originally posted code:
typedef struct{
variables
}item;
void myFunc(item *itemPointer){
item newItem;
newItem.variable = stuff;
}
int main(){
item * catcher;
myFunc(catcher);
printf("%s\n", catcher.variable);
}
A few issues.
Your program will not compile. variable has to have a type.
void myFunc(item *itemPointer){
item newItem;
newItem.variable = stuff;
}
stuff is not defined; item *itemPointer is not used.
item * catcher pointer has to point to allocated memory. It is not initialized.
Pass arguments via pointers and modify member of the structure like this:
void myFunc(item *itemPointer, const char *string){
itemPointer->variable = string ;
}
Solution like:
void myFunc(item *itemPointer)
{
itemPointer->variable = stuff;
// or
*itemPointer = someItem;
}
is possible, but it assumes that stuff or someItem is a global variable which is not the best programming practice IMO.
Retrieve value from pointer via -> not . operator.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char * variable;
}item;
void myFunc(item *itemPointer, const char *string){
itemPointer->variable = string ;
}
int main(){
item * catcher;
char *new_string = "new string";
catcher = malloc(sizeof(item));
myFunc(catcher, new_string);
printf("%s\n", catcher->variable);
free(catcher);
return 0;
}
OUTPUT:
new string
I have a major issue that is happening to my code, that I've been trying to fix for hours now.
The code below is the one relevant to the issue that I am having...
The method addBucket:
void addBucket(SPACE * hashmap,char * tempvalue, char * tempkey){
printf("BEGINNING OF FUNC...\n");
void *prevadd = hashmap[0];
char *value = varString(tempvalue);
char *key = varString(tempkey);
void *aftadd = hashmap[0];
printf("BUCKET %s - %s\n",value,key);
BUCKET *newBucket = malloc(sizeof(BUCKET *));
fillBucket(value,key,newBucket);
int hash = hashFunc(key);
printf("FILL, FULFILLED\n");
if(!hashmap[hash]){
hashmap[hash] = malloc(sizeof(BASE*));
hashmap[hash]->first = NULL;
}
ITEM *location;
location = hashmap[hash]->first;
//This creates a new item in the list, if there isn't any.
//It does this by initialising the base, called box.
if(!location){
hashmap[hash]->first = (ITEM *) calloc(1,sizeof(ITEM *));
hashmap[hash]->first->next = NULL;
hashmap[hash]->first->prev = NULL;
hashmap[hash]->first->data = newBucket;
}
//This instead adds a new item to the list.
else{
//This loop reaches the last ITEM in the linked list itself
while(location->next){
location = location->next;
}
//This initialises the newItem that will be added
ITEM *newItem = (ITEM *) calloc(1,sizeof(ITEM));
newItem->next = NULL;
newItem->data = newBucket;
newItem->prev = location;
location->next = newItem;
}
}
The declared structs that are used:
//Declares a struct called BUCKET.
//Serves as the bucket of the hash table.
typedef struct bucket{
char * value; //The value inputted.
char * key; //The key to be hashed.
}BUCKET;
//Declares a struct called ITEM.
//Holds the bucket, as well as the address to the next bucket.
//It also holds the address to the previous bucket.
typedef struct item{
struct bucket * data;
struct item * next;
struct item * prev;
}ITEM;
//Declares a struct called BASE.
//Serves as the base node for the linked lists.
//The amount of initialised linked lists is the same as the amount of bases.
typedef struct base{
struct item * first;
}BASE;
//Declares a struct of an array of BASES, meaning linked lists.
//Essentially defines the size of the hashspace.
typedef BASE *SPACE;
...And the method expandHashspace(); :
//Makes the size of the entire hashspace larger.
//Only takes a value larger than the current size due to possible data loss.
SPACE* expandHashspace(SPACE *hashmap, int newSize){
if(newSize>100 || newSize<hashSpaceSize){
printf("Exiting...\n");
return NULL;
}
else {
SPACE *nw = NULL;
nw = realloc(hashmap, sizeof(SPACE *) * newSize);
hashmap = nw;
hashSpaceSize = newSize;
return hashmap;
}
}
Here's also the initHashmap() method:
SPACE* hashmapInit(SPACE *hashmap){
hashmap = calloc(5, sizeof(SPACE *));
hashSpaceSize = 5;
return hashmap;
}
What I am doing here is initialising the hashmap, adding three buckets, expanding the hashmap, then adding three more buckets. Here's the order in more simple terms:
initHashmap();
addBucket(...); x3
expandHashmap();
addBucket(...); x3
However, on that last part, as soon as I run addBucket once, I get a SIGSEGV error. Checking through debugging, I realised something that was off.
Do you see the variables *prevadd and *aftadd? I added them while debugging to see what was happening to the address of hashmap[0]. Here is a picture of my results:
As you can see there, the address of hashmap[0] varied wildly during those two char * lines. Specifically, the change of address happens on the char *value line.
Please go easy on me, as I've just started learning C 3 months ago, and I am still incredibly unaccustomed to memory allocation. If the error is obvious, please point it out, and if I have some problem with the way that I am allocating memory, or freeing it, I am more than happy to hear them (my code has a pretty major heisenbug that I cannot fix for the life of me, but that's beside the point).
Thank you in advance... Sorry for all the recent questions.
update : forgot to add varString();...
char* varString(const char *origString){
size_t i;
for(i = 0;origString[(int)i]!='\0';i++){}
if(origString[i-1]=='\n') i-=2;
char *newString = malloc(i);
for(int j = 0; j <= i; j++){
newString[j] = origString[j];
}
newString[i+1] = '\0';
return newString;
}
This is not an answer, but it needed more formatting than would fit in a comment:
Note that you are writing "Value No. 1"
Note the value of aftadd is 0x756c6156
In memory, assuming a little-endian machine, the layout of the number in aftadd would be:
0x56 0x61 0x6c 0x75
In ASCII these would be:
'V' 'a' 'l' 'u'
Hint hint.
I am trying to make an implementation of an n-ary tree in C. When running it I get the following error:
sibling(1143,0x7fff7e925000) malloc: *** error for object 0x7f946b4032c8: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
I am unsure what is causing the error. As it says it seems that I am writing to an object that was freed. But in my code I do not free any of the memory allocated. I am new to c to this confused me very much. I tried debugging with gdb and it says the error is caused by the printTree(); call in main where I am recursively trying to print the tree. Hope you can help me understand the issue :-).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
unsigned int utility;
unsigned int probability;
} Child;
typedef struct {
unsigned int level;
unsigned int player;
unsigned int nChildren;
Child *children;
} Data;
typedef struct sNaryNode{
Data *data;
struct sNaryNode *kid;
struct sNaryNode *sibling;
} NaryNode;
NaryNode* createNode(Data data){
NaryNode *newNaryNode = malloc(sizeof (NaryNode*));
newNaryNode->sibling = NULL;
newNaryNode->kid = NULL;
newNaryNode->data = &data;
return newNaryNode;
}
NaryNode* addSibling(NaryNode* n, Data data){
if(n == NULL) return NULL;
while(n->sibling)
n = n->sibling;
return (n->sibling = createNode(data));
}
NaryNode* addChild(NaryNode* n, Data data){
if(n == NULL) return NULL;
else if(n->kid)
return addSibling(n->kid, data);
else
return (n->kid = createNode(data));
}
void printTree(NaryNode* n) {
if(n == NULL) return;
if(n->sibling) {
printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name);
printTree(n->sibling);
}
else if(n->kid) {
printf("%u %u %u %u %u %s", n->data->level, n->data->player, n->data->nChildren, n->data->children[0].probability, n->data->children[0].utility, n->data->children[0].name);
printTree(n->kid);
}
else {
printf("The tree was printed\n");
}
}
int main(void) {
NaryNode *root = calloc(1, sizeof(NaryNode));
Data data;
data.level = 1;
data.player = 1;
data.nChildren = 2;
data.children = calloc(data.nChildren, sizeof data.nChildren);
data.children[0].probability = 50;
data.children[0].utility = 1;
data.children[0].name = "Kom med det første tilbud (anchor)";
data.children[1].probability = 50;
data.children[1].utility = 1;
data.children[1].name = "Afvent modspilleren kommer med første tilbud";
*root = *createNode(data);
int i = 0;
for(i=0; i<root->data->nChildren; i++) {
addChild(root, data);
}
printTree(root);
}
There are various errors in your code.
Allocating an incorrectly sized memory block :
data.children = calloc(data.nChildren, sizeof data.nChildren);
data.children is an array of Child structures, yet you're allocating structures whose size is equal to sizeof(unsigned int), due to data.nChildren being an unsigned int.
Taking the address of a temporary variable and storing it for later usage :
NaryNode* createNode(Data data){
newNaryNode->data = &data;
}
data in createNode only exists for as long as the function is running : in this case, you're taking the address of the local variable data and storing it in the structure that you're returning for later usage. This is a very bad idea, since this pointer will refer to an object that doesn't exist anymore after the function returns.
Keep in mind that you don't need to pass a copy of the Data object into createNode in your current code, since there is really only one Data object in the whole program. Thus, you can change the prototype of createNode to createNode(Data* data), and pass the address of the Data structure that you create in main. Doing anything more involved than that, though, would require deep-copying the structure, I think.
Incorrectly managing the objects' lifetime.
NaryNode *root = calloc(1, sizeof(NaryNode));
*root = *createNode(data);
createNode returns an NaryNode*. However, you never actually assign it to an NaryNode* so that you can free it later. Instead, the pointer to the object that the function returns is known only during the *root = *createNode(data) invocation, and irrevocably lost later on. You do, however, retain the contents of the object due to dereferencing it and copying it into root : the object itself, however, as returned from createNode, is lost and not recoverable, unless pointers to it still exist in the tree.
Here is another problem. This line does not allocate space for a NaryNode, but only for a pointer to a NaryNode:
NaryNode *newNaryNode = malloc(sizeof (NaryNode*));
Whew! Long title...here's some pseudo-code to explain that verbiage:
int main(){
int* ptr = function1(); //the data that ptr points to is correct here
function2(ptr);
}
int function2(int* ptr){
//the data that ptr points to is still correct
int i;
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++); //since ptr points to a contiguous block of memory
function3(ptr);
}
int function3(int* ptr){
//the data that ptr points to is INCORRECT!!!
}
Why would the data in function3 be incorrect?
Note: function1 performs a malloc() and returns the pointer to that memory.
ACTUAL CODE
#include <stdlib.h>
#include <stdio.h>
//Structures
struct hash_table_data_
{
int key, data;
struct hash_table_data_ *next, *prev;
};
struct hash_table_
{
int num_entries;
struct hash_table_data_ **entries;
};
typedef struct hash_table_data_ hash_table_data;
typedef struct hash_table_ hash_table;
//Prototypes
hash_table *new_hash_table(int num_entries);
int hash_table_add(hash_table *ht, int key, int data);
int hash_table_loader(hash_table* ht);
//Main
int main()
{
int num_entries = 8;//THIS MUST BE AUTOMATED
hash_table* ht = new_hash_table(num_entries);
hash_table_loader(ht);
return 0;
}
//Function Definitions
hash_table *new_hash_table(int num_entries)
{
hash_table* ht = (hash_table*) malloc(sizeof(hash_table));
hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
int i;
for (i=0;i<num_entries;i++)
{
array[i].key = -1;
array[i].data = -1;
array[i].next = NULL;
array[i].prev = NULL;
}
ht->entries = &array;
ht->num_entries = num_entries;
return ht;
}
int hash_table_add(hash_table *ht, int key, int data)
{
//VERIFY THAT THE VALUE ISN'T ALREADY IN THE TABLE!!!!!!!!!!!
int num_entries = ht->num_entries;
hash_table_data* array = *(ht->entries); //array elements are the LL base
int hash_val = key%num_entries;
printf("adding an element now...\n");
printf("current key: %d\n", array[hash_val].key);
int i;
for(i=0;i<num_entries;printf("%d\n", (*(ht->entries))[i].key),i++);//DATA IS INCORRECT!!!!
if (array[hash_val].key == -1)//is this the base link?
{
printf("added a new base link!\n");
array[hash_val].key = key;
array[hash_val].data = data;
array[hash_val].next = NULL;
array[hash_val].prev = &(array[hash_val]);
}
else//since it's not the base link...do stuff
{
hash_table_data* new_link = malloc(sizeof(hash_table_data));
new_link->key = key;//set the key value
new_link->data = data;//set the data value
if (array[hash_val].next == NULL)//we must have the second link
{
printf("added a new second link!\n");
new_link->prev = &(array[hash_val]); //set the new link's previous to be the base link
array[hash_val].next = new_link; //set the first link's next
}
else//we have the 3rd or greater link
{
printf("added a new 3rd or greater link!\n");
hash_table_data next_link_val = *(array[hash_val].next);
while (next_link_val.next != NULL)//follow the links until we reach the last link
{
next_link_val = *(next_link_val.next);//follow the current link to the next
}
//now that we've reached the last link, link it to the new_link
next_link_val.next = new_link; //link the last link to the new link
new_link->prev = &(next_link_val); //link the new link to the last link
}
}
return 0;
}
int hash_table_loader(hash_table* ht)
{
int i;
for(i=0;i<(ht->num_entries);printf("%d\n", (*(ht->entries))[i].key),i++); //DATA IS STILL CORRECT HERE
FILE *infile;
infile = fopen("input.txt", "r");
while(!feof(infile))
{
int key,data;
fscanf(infile, "%d %d", &key, &data);
hash_table_add(ht, key, data);
}
fclose(infile);
}
Note: Issue occurring the first time hash_table_add() is called.
Your first problem is here:
ht->entries = &array;
You cause the structure to hold a hash_table_data** which points to the variable hash_table_data* array which is local to the function; then you exit the function and return a pointer to the structure. The structure still exists (it was allocated via malloc(), and the stuff that array points to still exists, but array itself does not. Accordingly, this pointer within the structure is now invalid.
As far as I can tell, there is no reason for you to be holding a pointer-to-pointer here. Just use hash_table_data* as the entries type, and copy array into that struct member. Pointers are values too.
I guess you iterate incorrectly
for(i=0;i<length;printf("%d\n", (*ptr)[i]), i++);
this is nonsense.
You should rewrite it as this:
for(i=0;i<length;i++)
printf("%d\n", ptr[i]);
(*ptr)[i] is just wrong, it doesn't make sense if you think about it.
*ptr is the first element of the pointed-to array of ints.
ptr[i] is thi ith one, this is what you need.
Please, read Section 6 carefully.
A couple of advises based on this question:
Don't write overcomplicated code like this for statement with comma operator used, it just rarely needed and leads not only to confusion, but to mistakes (although no mistakes with it in this particular example)
Look carefully for mistakes, don't blame everything on functions. If your code doesn't work, try finding the exact place which is wrong and prove it. In this example people who tested your code were right: functions are definitely not the cause of the error.
hash_table *new_hash_table(int num_entries)
{
hash_table* ht = (hash_table*) malloc(sizeof(hash_table));
hash_table_data* array = malloc(num_entries * sizeof(hash_table_data));
// ....
ht->entries = &array; // Problem
// ...
return ht;
} // Life time of array ends at this point.
You are taking the reference of the local variable array and assigning it to ht->entries which is no more valid once the function returns.
I have a problem with this small program. It added some value to list. If I uncomment //printf("%d",first->val); the program gives error. Everything seems to be ok ;(
#include <stdio.h>
#include <stdlib.h>
typedef struct element {
struct element *next;
int val;
} el_listy;
el_listy *first = 0;
void add_to_list(el_listy *lista, int value)
{
if(lista == 0)
{
lista = malloc (sizeof(el_listy));
lista->val = value;
lista->next = 0;
printf("added as first \n");
}
else
{ printf("added as fsecond \n");
el_listy *wsk = lista,*tmp;
while(wsk->next != 0) wsk = wsk->next;
tmp = malloc (sizeof(el_listy));
tmp->val = value;
tmp->next = 0;
wsk->next = tmp;
}
}
int main ()
{
add_to_list(first,2);
add_to_list(first,4);
//printf("%d",*first->val);
system("pause");
return 0;
}
first->val is just like (*first).val, you can't use them both. also, as missingno said, add_to_list never changes first you should pass it's address as argument, not the pointer itself, meaningadd_to_list(&first,4); (and change the implementation of add_to_list as well)
Your program never changes the value of first. It remains a null pointer and thus gives an error when dereferenced.
-> already follows a pointer, so the * tries to treat first as pointer to pointer to el_listy. You might find cdecl helpful.
You should use either (*first).val or first->val. Otherwise you get the wrong level of indirection.
Yes, it's a simple mistake.
fitsr won't change after *add_to_list()* function is called.
You should define function like this:
add_to_list(El_list **lista, ...)