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.
Related
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]);
I'm trying to solve a problem I'm having with a function that will create a new struct objects and then put it in an dynamic array. I have tried multiple variations but i keep running into various problems. This is what I'm working with right now, but I'm getting a memory access problem.
typedef struct {
int keynr;
int access;
time_t lastused;
} keycard;
void keyCreate(keycard *cardList, int keyid) {
cardList[keyid].keynr = keyid + 100;
cardList[keyid].access = 1;
cardList[keyid].lastused = 0.0;
}
int main () {
keycard *cardList = 0;
cardList = malloc(sizeof(keycard) * 1);
keyCreate(&cardList, 0);
printf("%d", cardList[0].access);
This code gives me: Exception thrown: read access violation.
cardList was 0x64.
I've been reading alot about pointers and memmory allocation but obviously i am missing something..
You if you want to duynamically add new cards to the array, you need to wrap it in another data structure:
typedef struct
{
int keynr;
int access;
time_t lastused;
} keycard;
typedef struct
{
keycard *keyarray;
size_t size;
}keystorage;
int keyCreate(keystorage *cardList, size_t keyid)
{
if (cardList -> keyarray == NULL || keyid + 1 > cardList -> size)
{
keycard *new = realloc(cardList -> keyarray, sizeof(*(cardList -> keyarray)) * (keyid + 1));
if(!new) return -1; //error
cardList -> keyarray = new;
cardList -> size = keyid + 1;
}
cardList -> keyarray[keyid].keynr = keyid + 100;
cardList -> keyarray[keyid].access = 1;
cardList -> keyarray[keyid].lastused = 0.0;
return 0; //OK
}
int main (void) {
keycard key;
keystorage cards = {NULL, 0};
keyCreate(&cards, 500);
printf("%d", cards.keyarray[500].access);
return 0;
}
You are passing the incorrect type to keyCreate. This function expects a pointer to keycard, but you are passing it a double pointer instead. The & means "take the address of", which turns cardList into a keyCard** type. Instead, consider the following:
void keyCreate(keycard *cardList, int keyid) {
cardList[keyid].keynr = keyid + 100;
cardList[keyid].access = 1;
cardList[keyid].lastused = 0; // time_t is most likely a signed integer
}
int main (void) {
keycard *cardList = malloc(sizeof(keycard) * 1);
// always check if malloc succeeds, and if it does not, handle the error somehow
if (cardList == NULL)
{
fprintf(stderr, "Insufficient mem\n");
return -1;
}
keyCreate(cardList, 0);
printf("%d\n", cardList[0].access); // the \n will flush the output and
// put each item on its own line
// cleanup when you're done, but the OS will do this for you when the
// process exits also
free(keyCreate);
return 0;
}
Also, time_t is most likely a signed integer (What is ultimately a time_t typedef to?), so assigning it to 0.0 is probably not right, but you'll need to check what it typedefs to on your system.
Finally, I assume this is just an MCVE, but I'd advise against mallocing in this case. The 2 primary reasons to malloc are when you don't know how much data you'll need until runtime, or you need "a lot" of data. Neither of those are true in this case. Just from what you've presented, I'd probably do the following:
#define NUM_KEY_CARDS 1
void keyCreate(keycard *cardList, int keyid) {
cardList[keyid].keynr = keyid + 100;
cardList[keyid].access = 1;
cardList[keyid].lastused = 0; // time_t is most likely a signed integer
}
int main (void) {
keycard cardList[NUM_KEY_CARDS];
for (int keyid=0; keyid<NUM_KEY_CARDS; keyid++)
{
keyCreate(cardList+keyid, keyid);
// or keyCreate(&(cardList[keyid]), keyid);
printf("%d\n", cardList[keyid].access);
}
return 0;
}
const static int VECTOR_BASIC_LENGTH = 20;
struct m_vector
{
void* my_vector;
size_t my_capacity;
size_t my_head;
};
typedef struct m_vector Vector;
Vector creat_Vector(size_t size,void *judge)
{
Vector _vector;
size = size?size:VECTOR_BASIC_LENGTH;
_vector.my_capacity = size;
_vector.my_head = 0;
//How I write the following two lines
_vector.my_vector = malloc(sizeof(*judge) * size);
return _vector;
}
The type of judge is uncertain,so I pass a void pointer as a parameters.I need the size of *judge to allocate memory to _vector.my_vector,for example if I use:
int *a;
creat_Vector(5,a);
I want the following line:
_vector.my_vector = malloc(sizeof(*judge)*size);
is equal to:
_vector.my_vector = malloc(sizeof(*a)*5);
How could I achieve this function.Using pure C
There is a forbidden thing done in your code.
You statically (at compile time) allocate/declare a local _vector of type Vector in your function creat_Vector. Then you return this object to the outside world. However, when you are exiting your function, all local data is dead. So, you should absolutely rethink this.
One suggestion would be:
int init_Vector(Vector* _vect, size_t size, unsigned int ptr_size)
{
size = size?size:VECTOR_BASIC_LENGTH;
_vect->my_capacity = size;
_vect->my_head = 0;
_vect->my_vector = malloc(size*ptr_size);
if (_vect->my_vector) {
return 0;
}
return 1;
}
Then:
Vector _vector;
char *a;
if (init_Vector(&_vector, 5, sizeof(char)) == 0) {
printf("Success!\n");
}
else {
printf("Failure!\n");
/* treat appropriately (return error code/exit) */
}
/* do whatever with a (if needed) and _vector*/
I have a struct which has a char * to act as it's name for finding it. I also have an array of struct declared. I am trying to assign a struct a name, but the problem I am having is the char * is continuing to change values to whatever the last name is set. This is wrecking havoc for the logic of my code. I have tried using malloc(), but that did not change the results.
code:
struct foo {
char* label;
}
typedef struct foo fum;
fum foolist[25];
/*initialize all elements in foo list to be "empty"*/
bool setArray(char* X) {
for(int i =0; i <25;i++) {
if(strncmp("empty", foolist[i].label,5*sizeof(char))==0) {
//tried char* temp = (char*)malloc(32*sizeof(char));
//foolist[i].label = temp; no change.
foolist[i].label = X;
return true;
}
}
return false;
}
I want label to not change with 'X' once the declaration is made, i have tried using malloc(), probably not correctly though.
You can do either:
foolist[i].label = malloc(strlen(X) + 1);
if ( !foolist[i].label ) {
perror("couldn't allocate memory"):
exit(EXIT_FAILURE);
}
strcpy(foolist[i].label, X);
or, if you have strdup() available:
foolist[i].label = strdup(X);
if ( !foolist[i].label ) {
perror("couldn't allocate memory"):
exit(EXIT_FAILURE);
}
So when I call the following function I get a seg fault:
void destroyVariableVector(VariableVector* variableVector) {
if (variableVector) {
free(variableVector->variables); // <== Seg Fault here
free(variableVector);
}
}
And this is what my structs look like:
struct _Variable {
char *variableName;
char *arrayOfElements;
int type;
int32_t address;
};
typedef struct _Variable Variable;
struct _VariableVector {
int size; // elements full in array
int capacity; // total available elements
Variable *variables;
};
typedef struct _VariableVector VariableVector;
and here are their init methods:
Variable* initVariable(char *variableName, char *arrayOfElements,
int32_t address, int type) {
Variable* initialVariable = malloc(sizeof(*initialVariable));
if (initialVariable != NULL ) {
initialVariable->variableName = strdup(variableName);
initialVariable->arrayOfElements = strdup(arrayOfElements);
initialVariable->address = address;
initialVariable->type = type;
}
return initialVariable; // may be NULL
}
VariableVector* initVariableVector() {
VariableVector* initialVariableVector = malloc(sizeof(VariableVector));
if (initialVariableVector != NULL ) {
initialVariableVector->size = 0;
initialVariableVector->capacity = VECTOR_INITIAL_CAPACITY;
initialVariableVector->variables = malloc(
sizeof(Variable) * VECTOR_INITIAL_CAPACITY);
}
return initialVariableVector;
}
Can anyone explain how I am getting a seg fault when I call my destroyVariableVector() method???
Here is the code that calls the above functions:
VariableVector* variableVector = initVariableVector();
// add some variables to variableVector
writeOutVariables(variableVector, outputFilePointer);
destroyVariableVector(variableVector);
where the method writeOutVariables looks like:
void writeOutVariables(VariableVector *variableVector, FILE *outputFilePointer) {
// write out all variables within the variableVector to the output file
int variableVectorSize = variableVector->size;
int i = 0;
// start from the first variable in the varaibleVector to the last variable
while (i < variableVectorSize) {
// 0 = label; 1 = variable ascii string; 2 = variable number array;
int currentType = variableVector->variables->type;
if (currentType == 1) {
writeToFileASCIICharArrayInReverseOrder(
variableVector->variables->arrayOfElements,
outputFilePointer);
i++;
} else if (currentType == 2) {
char currentNumberArray[MAXIMUM_LINE_LENGTH + 1]; // + 1 for terminating char
strcpy(currentNumberArray,
variableVector->variables->arrayOfElements);
char* currentNumber = strtok(currentNumberArray, " ,\t\n");
while (currentNumber != NULL ) {
// you have not yet reached the end of the numberArray
int integer = atoi(currentNumber);
writeToFileIntegerAs32bits(integer, outputFilePointer);
currentNumber = strtok(NULL, " ,\t\n");
}
i++;
} else {
i++;
}
variableVector->variables++; // move on to next variable
}
}
In writeOutVariables, you're incrementing variableVector->variables to iterate through your list. However, this because it's a pointer, you're incrementing the actual value and hence moving the pointer beyond the end. Then, when you try to free variables, you're actually freeing memory that wasn't previously malloced.
Instead, initialize a pointer to variableVector->variables inside writeOutVariables so you don't clobber that pointer.
void writeOutVariables(VariableVector *variableVector, FILE *outputFilePointer) {
Variable *tmpVariables = variableVector->varaibles;
// The original code
// ...
tmpVariables++;
}