Update value by index - array of void pointers inside struct - c

I'm trying to create array of void pointers inside my struct to see if that is possible. I want to be in charge of the memory allocation and to be able to update the value for each array by index. The value data type is not specified as i want to accept any data type.
This is what i did:
typedef struct {
void ** value;
} bucket;
void updateValue(bucket * data, index, void * value)
{
if(data->value[index] == NULL)
{
data->value[index] = (void*)calloc(1, sizeof(void*));
}
data->value[index] = value;
}
bucket * clients = calloc(1, sizeof(bucket));
clients->value = (void **)calloc(3, sizeof(void*));
clients->value[0] = NULL;
clients->value[1] = NULL;
clients->value[2] = NULL;
updateValue(clients, 0, (void*) (int)124);
printf("Client0 Value: value: %d\n", (int)&clients->value[0]);
The code compile, but does not output 124 as value. I don't know what is wrong. Can someone please help me to correct it and explain what wrong so i can learn?

You stored (void*) (int)124 to clients->value[0].
This means that the value is stored to the element, not as the address of the element.
Because of that , the printing statement should be
printf("Client0 Value: value: %d\n", (int)clients->value[0]);
without the extra &.
Also note that the part
if(data->value[index] == NULL)
{
data->value[index] = (void*)calloc(1, sizeof(void*));
}
should be removed to avoid memory leaks caused by allocating unused buffer and soon overwriting its address.
Maybe you want this (allocating buffer and copy the data there):
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for using memcpy() */
typedef struct {
void ** value;
} bucket;
void updateValue(bucket * data, index, void * value, size_t valueSize)
{
data->value[index] = realloc(data->value[index], valueSize);
memcpy(data->value[index], value, valueSize);
}
bucket * clients = calloc(1, sizeof(bucket));
clients->value = (void **)calloc(3, sizeof(void*));
clients->value[0] = NULL;
clients->value[1] = NULL;
clients->value[2] = NULL;
int value = 124;
updateValue(clients, 0, &value, sizeof(value));
printf("Client0 Value: value: %d\n", *(int*)clients->value[0]);

Related

Error using memcpy : "Access violation reading location 0x0000000000000000"

I am trying to write something similar to std::vector but in c to store a bunch of mathematical vectors.
Here is the line that is casing the error.
pVl->pData = memcpy(pNewData, pVl->pData, sizeof(pVl->pData));
My Intention: Copy data from pVl->pData to pNewData. Then assign the return value, which is the
pointer to start of the newly copied data memory and assign it to pVl->pData. I am not sure what I am doing wrong.
MRE:
#include <stdlib.h>
#include <string.h>
typedef enum R_Code { R_OK, R_WARNING, R_FAIL, R_FATAL } R_Code;
struct Vector2_s
{
float x;
float y;
} const Default_Vector2 = { 0.0f, 0.0f };
typedef struct Vector2_s Vector2;
struct Vector2List_s
{
//current capacity of the List
size_t capacity;
//current size of the list
size_t size;
//data buffer
Vector2* pData;
} const Default_Vector2List = { 0, 0, NULL };
typedef struct Vector2List_s Vector2List;
R_Code Vector2List_ReAllocateMem(Vector2List* pVl) {
if (pVl->capacity == 0) {
pVl->capacity++;
}
Vector2* pNewData = malloc(pVl->capacity * 2 * sizeof(Vector2));
if (pNewData == NULL) {
return R_FAIL;
}
pVl->capacity *= 2;
pVl->pData = memcpy(pNewData, pVl->pData, sizeof(pVl->pData));//EXPECTION THROWN IN THIS LINE
free(pNewData);
return R_OK;
}
R_Code Vector2List_PushBack(Vector2List* pVl, const Vector2 v) {
if (pVl->size == pVl->capacity) {
R_Code rcode = Vector2List_ReAllocateMem(pVl);
if (rcode == R_FAIL) {
return rcode;
}
}
pVl->pData[pVl->size] = v;
pVl->size++;
return R_OK;
}
int main() {
Vector2List vl = Default_Vector2List;
Vector2List_PushBack(&vl, Default_Vector2);
return 0;
}
Within the function Vector2List_ReAllocateMem you allocated dynamically memory
Vector2* pNewData = malloc(pVl->capacity * 2 * sizeof(Vector2));
then in this statement
pVl->pData = memcpy(pNewData, pVl->pData, sizeof(pVl->pData));
you are using the null pointer pVl->pData as a source of data that invokes undefined behavior.
Moreover you freed the allocated memory.
free(pNewData);
Also using this expression sizeof(pVl->pData) does not make a sense.
It seems what you need is the following
pVl->pData = pNewData;
Though if you are going to reallocate memory then instead of malloc you need to use realloc.
You need to rewrite the function entirely.

Ensure the allocation of memory is of the right size [duplicate]

This question already has answers here:
sizeof(value) vs sizeof(type)?
(3 answers)
Closed 2 years ago.
I seem to have a problem that I cant comprehend, the lab assistants said "Your memory allocation will not allocate the correct size, you need to use the size of the type itself instead of the variable.".
I have tried to use sizeof (struct object) like this printf("%d", sizeof(struct object));to see the size and it returns 36. In the allocation the size is the same as the struct object so I am kinda lost to why it would allocate wrong size. The allocation seems to work for me correctly when I run it, and in the debugger it doesn't show any errors, so if anyone could have a look, I would really appreciate it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NameLength 20
#define UnitLenght 10
struct object
{
char name[NameLength];
float amount;
char unit[UnitLenght];
};
struct inventory
{
struct object *add;
int nrOfobject;
};
void allocateMemory(struct inventory *allItem);
int main(void)
{
struct inventory shopping = {NULL, 0};
allocateMemory(&shopping);
return 0;
}
void allocateMemory(struct inventory *allItem)
{
struct object *tempurary;
if (allItem->nrOfobject == 0)
tempurary = (struct object *)calloc(1, sizeof(*tempurary));
else
tempurary = (struct object *)realloc(allItem->add, sizeof(*tempurary)*(allItem->nrOfobject +1));
allItem->add = tempurary;
}
void allocateMemory(struct inventory *allItem)
{
struct object *tempurary;
if (allItem->nrOfobject == 0)
tempurary = (struct object *)calloc(1, sizeof(*tempurary));
else
tempurary = (struct object *)realloc(allItem->add, sizeof(*tempurary)*(allItem->nrOfobject +1));
allItem->add = tempurary;
}
The size looks correct, although I would remove the unnecessary cast, and the clearing of the first element (since we don't zero-out the subsequent ones). Also, check the result of realloc() before overwriting the pointer (otherwise we can leave a memory leak):
int allocateMemory(struct inventory *allItem)
{
struct object *temporary;
if (allItem->nrOfobject == 0) {
temporary = malloc(sizeof *temporary);
} else {
temporary = realloc(allItem->add, (sizeof *temporary)*(allItem->nrOfobject + 1));
}
if (!temporary) {
return 0;
}
allItem->add = temporary;
return ++allItem->nrOfobject;
}

Abort trap 6 malloc

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*));

C: Stack element overwritten by a function call

I'm doing a school assignment, I've I've run into 2 problems. I have to simulate stacks, with arrays.
My current code is as follows:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int capacity;
int * array;
int size;
} stack_tt;
int pop(stack_tt * stack_p);
void push(stack_tt * stack_p, int value);
int top(stack_tt * stack_p);
stack_tt * newStack(void);
int empty(stack_tt * stack_p);
int main() {
stack_tt * myStack = newStack();
push(myStack, 123);
push(myStack, 99);
push(myStack, 4444);
while (!empty(myStack)) {
int value;
value = pop(myStack);
printf("popped: %d\n", value);
}
return 0; }
stack_tt * newStack(){
stack_tt * newS = malloc(sizeof(stack_tt) * 20);
(*newS).capacity = 1;
(*newS).size = 0;
return newS;
}
void push(stack_tt * stack_p, int value){
if ((*stack_p).size >= (*stack_p).capacity) {
(*stack_p).capacity*=2;
//realloc(stack_p, stack_p->capacity * sizeof(stack_tt));
}
(*stack_p).array = &value;
(*stack_p).size++;
}
int pop(stack_tt * stack_p){
(*stack_p).size--;
int fap = *(*stack_p).array;
return fap;
}
int empty(stack_tt * stack_p){
if ((*stack_p).size >= 1)
return 0;
return 1;
}
Fist of, when I call the line
while(!empty(myStack))
It changes the value in my array to 1.
secondly I'm not able to change individual values in my array, whenever I try things like:
(*stack_p).array[0] = value;
It doesn't know where in the memory to look.
I hope someone is able to help me out :)
There are a couple of problems with the code as I see it.
Lets take the push function where you do
(*stack_p).array = &value;
That will make the array structure member point to the local variable value, and once the function returns the variable cease to exist leaving you with a stray pointer and using that pointer will lead to undefined behavior.
The second problem with that code is that your stack will only be pointing (illegally) to the last element added.
You must allocate memory explicitly for array and use capacity to keep track of how much memory is allocated. The use size as an index into the allocated array for the pushing and popping. Something like
stack_tt * newStack(){
stack_tt * newS = malloc(sizeof(stack_tt)); // Only allocate *one* structure
newS->capacity = 0; // Start with zero capacity
newS->size = 0;
newS->array = NULL;
return newS;
}
void push(stack_tt * stack_p, int value){
if (stack_p->size + 1 > stack_p->capacity){
// Increase capacity by ten elements
int new_capacity = stack_p->capacity + 10;
int * temp_array = realloc(stack_p->array, new_capacity * sizeof(int));
if (temp_srray == NULL)
return;
stack_p->capacity = new_capacity;
stack_p->array = temp_array;
}
stack_p->array[stack_p->size++] = value;
}
int pop(stack_tt * stack_p){
if (stack_p->size > 0)
return stack_p->array[--stack_p->size];
return 0;
}
int empty(stack_tt * stack_p){
return stack_p->size == 0;
}
There is no need to allocate space for 20 structs of type stack_tt, you only need to allocate space for one:
stack_tt * newS = malloc(sizeof(stack_tt));
however you need to allocate space for elements of the struct member array:
newS->array = malloc( sizeof(int)*20);
newS->size = 0;
newS->capacity = 20;
now you can use the array member.
When you push a value to the 'stack', you shouldn't overwrite the array member with the address of the local variable, that doesn't make sense and will cause undefined behavior in addition of loosing the previously allocated memory. Instead simply assign the value to the member array, in the function push:
stack_p->array[stack_p->size] = value;
stack_p->size++;
Similarly when you pop an element, take the current element from the member array:
stack_p->size--;
int fap = stack_p->array[stack_p->size];
The rest of the functions and code should be fixed in the same manner.
You're code is good, but probably you didn't understand the usage of realloc:
//realloc(stack_p, stack_p->capacity * sizeof(stack_tt));
This function returns a pointer to the newly allocated memory, or NULL if the request fails.
The realloc (as the function suggests) takes the memory pointed by the pointer you pass, and copies that memory block in a new and resized block. So the right code should be.
stack_p->array = realloc(stack_p->array, stack_p->capacity * sizeof(stack_tt));
This other line is wrong:
(*stack_p).array = &value;
Change it with:
stack_p->array[stack_p->size] = value;
Another little suggestion, every (*stack_p). can be replaced by stack_p->, which is more elegant.
In the newStack() you're mallocing 20 structs which is kinda useless. You just need one.
Then you should malloc the array for the first time:
newS->array = malloc(sizeof(int));
newS->capacity = 1;

C Pointer and Memory Allocation: Realloc Arrays and Pointer Passing

For those experienced with C, this will be a simple memory allocation/referencing problem:
Here are my data structures:
struct configsection {
char *name;
unsigned int numopts;
configoption *options;
};
typedef struct configsection configsection;
struct configfile {
unsigned int numsections;
configsection *sections;
};
typedef struct configfile configfile;
Here are my routines for initializing a configsection or configfile, and for adding a configsection to a configfile:
// Initialize a configfile structure (0 sections)
void init_file(configfile *cf) {
cf = malloc(sizeof(configfile));
cf->numsections = 0;
}
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
// Add a section to a configfile
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
cf->numsections = cf->numsections + 1;
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*cf->numsections);
// Insert the new item
cf->sections[cf->numsections] = *sec;
}
I believe my problem originates in my init_sec() function. Here is an example:
int main(void) {
// Initialize test configfile
configfile *cf;
init_file(cf);
// Initialize test configsections
configsection *testcs1;
init_sec(testcs1, "Test Section 1");
// Try printing the value that should have just been stored
printf("test name = %s\n", testcs1->name);
Although the printf() in init_sec() successfully prints the name I just stored in the configsection, attempting the same thing in the printf() of main() produces a segmentation fault. Further, addsec() produces a segmentation fault.
This routine should be
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
(*cf)->sections = NULL; // You forgot to initialise this.
}
i.e. called by init_file(&myconfigfilepointer); so the malloc return value gets passed back.
Need to do the same trick for init_sec
This function is incorrect - here is a corrected version
void add_sec(configfile *cf, configsection *sec) {
// Increase the size indicator by 1
// Reallocate the array to accommodate one more item
cf->sections = realloc(cf->sections, sizeof(configsection)*(1 + cf->numsections));
// Insert the new item
cf->sections[cf->numsections] = *sec; // Since arrays start at 0
cf->numsections = cf->numsections + 1;
}
You then need to adjust the calls in main
At no point do you initialise cf->sections, which means when you try to realloc it the first time, you're passing rubbish. Adding:
cf->sections = NULL;
to init_file should help.
You're also not checking any return codes, but you knew that yes?
You need to pass a pointer of the value to be updated... eg:
// Initialize a configfile structure (0 sections)
void init_file(configfile **cf) {
*cf = malloc(sizeof(configfile));
(*cf)->numsections = 0;
}
configfile *var;
init_file(&var);
printf("%d\n", var->numsections);
Otherwise you are just updating the local pointer *cf and not the original passed in value
You need to really rethink how function arguments are passed in C and what pointers are. Your problem has nothing to do with memory allocation. Rather, your code is assigning a pointer to dynamically allocated memory only to a local variable, of which the calling code knows nothing.
While you could solve the problem by passing a pointer to the caller's pointer (i.e. a double pointer), this is not necessarily the most elegant or most usual way of handling things. Rather, you should return the result of the allocation from the function. While you're at it, you should also use calloc to zero out the memory right away. Wrapping it all up:
typedef struct substuff_
{
int a;
double b;
} substuff;
typedef struct stuff_
{
unsigned int n;
substuff * data;
} stuff;
substuff * init_substuff()
{
substuff * const p = malloc(sizeof *p);
if (p) { p->a = 5; p->b = -0.5; }
return p;
}
stuff * init_stuff()
{
substuff * const p = init_substuff();
if (!p) return NULL;
stuff * const q = malloc(sizeof *q);
if (q) { q->n = 10; q->data = p; }
return q;
}
As an exercise, you should write the corresponding functions void free_substuff(substuff *) and void free_stuff(stuff *).
Yes, there is a problem in init_sec
// Initialize a configsection structure with a name (and 0 options)
void init_sec(configsection *sec, char *name) {
sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
}
You're just copying the name pointer here, which means, that it points to the original storage of name. If you'd call init_sec like this
configsection foobar()
{
configsection sec;
char name[80];
get_name(name);
init_sec(sec, name);
return sec;
}
The name pointer became invalid the moment foobar returned. You need to duplicate the string and keep your private copy around. In init_sec:
sec->name = strdup(name);
But there's more. In the very first line of init_sec you're overwriting the pointer that was passed to init_sec with the one of malloc. So the new pointer never gets passed back to the calle. Either use a pointer to a pointer, don't take a configsection pointer at all (after all, you're allocating), but just return the allocated pointer: Complete corrected function:
// Initialize a configsection structure with a name (and 0 options)
configsection* init_sec(char *name) {
configsection *sec = malloc(sizeof(configsection));
sec->numopts = 0;
sec->name = name;
printf("%s\n", sec->name);
return sec;
}

Resources