C memcpy() wont copy because size_t is uninitialized - c

#include <stdlib.h>
typedef struct stackObject
{
void* obj;
struct stackObject *next;
} StackObject_t;
typedef struct stackMeta
{
StackObject_t *stack;
size_t objsize;
int numelem;
} StackMeta_t;
//CREATE
StackMeta_t *mystack_create(size_t objsize)
{
StackMeta_t *elem;
elem = (StackMeta_t*)malloc(sizeof(StackMeta_t));
if(elem == NULL)
{
return NULL;
}
else
{
elem->stack = NULL; // my actual stack basically the first elem(the top)
elem->objsize = objsize; // size of the datatype
elem->numelem = 0; // total count of elem inside the stack
}
return elem;
}
//PUSH
int mystack_push(StackMeta_t *data_stack, void* obj)
{
if(data_stack == NULL)
{
return -1;
}
StackObject_t *nodeObject = NULL;
nodeObject = (StackObject_t*)malloc(sizeof(StackObject_t));
if(nodeObject == NULL)
{
return -1;
}
if(data_stack->stack == NULL)
{
nodeObject->next = NULL;
memcpy(nodeObject->obj, obj, data_stack->objsize);
data_stack->stack = nodeObject;
data_stack->numelem++;
}
else
{
nodeObject->next = data_stack->stack;
memcpy(nodeObject->obj, obj, data_stack->objsize);
data_stack->stack = nodeObject;
data_stack->numelem++;
}
return 0;
}
int main() {
StackMeta_t *METADATA = NULL;
int obj = 1;
METADATA = mystack_create(sizeof(int));
mystack_push(METADATA, &obj);
return 0;
}
This code is Stack with Linked List inside.
So I am trying to copy int obj value to void* obj. from my understanding objcan be any data type so i chose it to be an int type. I am using a visual online tool to see my heap memory and I saw that the value of the 3rd parameter is size_t objsize = 4.
I cannot pin point where my problem is and I have not tested if this has memory leaks.
can someone explain this to me with an example on how to copy void pointers?

Related

Cant insert Node to binary tree

I am trying to insert Node to Binary tree. This is my function for creating Node (rest is done).
void BVSCreate_function(TNodef *rootPtr, function_save token) {
TNodef *newPtr = malloc(sizeof(struct tnodef));
if (newPtr == NULL) {
fprintf(stderr, "99");
return;
}
TNodef init;
string initStr;
initStr.str = NULL;
initStr.length = 0;
initStr.alloc = 0;
newPtr = &init;
newPtr->content = &initStr;
newPtr->leftPtr = NULL;
newPtr->rightPtr = NULL;
newPtr->return_type = token.ret_value;
newPtr->parameters = token.param_count;
strCpyStr(newPtr->content, token.content);
rootPtr = newPtr;
}
void BVSInsert_function(TNodef *rootPtr, function_save token) {
if (rootPtr == NULL) {
BVSCreate_function(rootPtr, token);
} else {
if ((strCmpStr(token.content, rootPtr->content)) < 0) {
BVSCreate_function(rootPtr->leftPtr, token);
} else
if ((strCmpStr(token.content, rootPtr->content)) > 0) {
BVSCreate_function(rootPtr->rightPtr, token);
}
}
}
When TNodef and function_save are structs:
typedef struct {
string *content;
int param_count;
int ret_value;
} function_save;
typedef struct tnodef {
string *content;
struct tnodef *leftPtr;
struct tnodef *rightPtr;
int parameters;
int return_type;
} TNodef;
Where string is defined as this struct:
typedef struct {
char *str; // content of string
int length; // length of string
int alloc; // amount of memory allocated
} string;
strCpystr function :
int strCpyStr(string *s1, string *s2) {
int len2 = s2->length;
if (len2 > s1->alloc) {
if (((s1->str) = (char *)realloc(s1->str, len2 + 1)) == NULL) {
return 1;
}
s1->alloc = len2 + 1;
}
strcpy(s1->str, s2->str);
s1->length = len2 + 1;
return 0;
}
I am trying to create a node in binary tree and put there information from struct function_save.
But when I try to print this tree after insert it shows me that tree is still empty.
Your code in BVSCreate_function has undefined behavior because:
newPtr = &init; discards the allocated node and instead uses a local structure that will become invalid as soon as the function returns.
newPtr->content = &initStr; is incorrect for the same reason: you should allocate memory for the string too or possibly modify the TNodeDef to make content a string object instead of a pointer.
Function BVSInsert_function does not return the updated root pointer, hence the caller's root node is never updated. You could change the API, passing the address of the pointer to be updated.
There is also a confusion in BVSInsert_function: it should call itself recursively when walking down the tree instead of calling BVSCreate_function.
Here is a modified version:
/* Allocate the node and return 1 if successful, -1 on failure */
int BVSCreate_function(TNodef **rootPtr, function_save token) {
TNodef *newPtr = malloc(sizeof(*newPtr));
string *newStr = malloc(sizeof(*content));
if (newPtr == NULL || newStr == NULL) {
fprintf(stderr, "99");
free(newPtr);
free(newStr);
return -1;
}
newStr->str = NULL;
newStr->length = 0;
newStr->alloc = 0;
newPtr->content = newStr;
newPtr->leftPtr = NULL;
newPtr->rightPtr = NULL;
newPtr->return_type = token.ret_value;
newPtr->parameters = token.param_count;
strCpyStr(newPtr->content, token.content);
*rootPtr = newPtr;
return 1;
}
int BVSInsert_function(TNodef **rootPtr, function_save token) {
if (*rootPtr == NULL) {
return BVSCreate_function(rootPtr, token);
} else {
if (strCmpStr(token.content, rootPtr->content) < 0) {
return BVSInsert_function(&rootPtr->leftPtr, token);
} else
if ((strCmpStr(token.content, rootPtr->content)) > 0) {
return BVSInsert_function(&rootPtr->rightPtr, token);
} else {
/* function is already present: return 0 */
return 0;
}
}
}
Note also that function strCpyStr may write beyond the end of the allocated area is len2 == s1->alloc, assuming s1->len is the length of the string, excluding the null terminator.
Here is a modified version:
int strCpyStr(string *s1, const string *s2) {
int len2 = s2->length;
if (len2 >= s1->alloc) {
char *newstr = (char *)realloc(s1->str, len2 + 1);
if (newstr == NULL) {
return 1;
}
s1->str = newstr;
s1->alloc = len2 + 1;
}
strcpy(s1->str, s2->str);
s1->length = len2;
return 0;
}

I get a segmentation fault because of free even though i used malloc

i am writing a Generic ADT using C and i keep getting a segmentation fault when i free an element
PairResult pairClear(Pair pair)
{
if(pair == NULL)
{
return PAIR_NULL_ARGUMENT;
}
KeyElement key=pair->key;
DataElement data=pair->data;
if(key)
pair->free_key(key);//i get the Error here
if(data)
pair->free_data(data);
return PAIR_SUCCESS;
}
the memory for key and data is allocated :
Pair pairCreate( KeyElement key, DataElement data,
copyDataElements copy_data,
freeDataElements free_data,
copyKeyElements copy_key,
freeKeyElements free_key)
{
Pair pair = malloc(sizeof(*pair));
if(pair == NULL)
{
return NULL;
}
pair->copy_data=copy_data;
pair->copy_key=copy_key;
pair->free_data=free_data;
pair->free_data=free_key;
KeyElement new_string_key = copy_key(key);
DataElement new_string_data = copy_data(data);
if((new_string_key == NULL) || (new_string_data == NULL))
{
pairDestroy(pair);
return NULL;
}
pair->key = new_string_key;
pair->data = new_string_data;
return pair;
}
this pairDestroy
void pairDestroy(Pair pair)
{
if(pair == NULL)
{
return;
}
#ifndef NDEBUG
PairResult result =
#endif
pairClear(pair);
assert(result == PAIR_SUCCESS);
free(pair);
}
these are the copy functions used:
static KeyElement copyKeyInt(KeyElement n) {
if (!n) {
return NULL;
}
int *copy = malloc(sizeof(*copy));
if (!copy) {
return NULL;
}
*copy = *(int *) n;
return copy;
}
static DataElement copyDataChar(DataElement n) {
if (!n) {
return NULL;
}
char *copy = malloc(sizeof(*copy));
if (!copy) {
return NULL;
}
*copy = *(char *) n;
return (DataElement) copy;
}
and these are the free functions used
static void freeInt(KeyElement n) {
free(n);
}
static void freeChar(DataElement n) {
free(n);
}
and here is the struct of pair
struct Pair_t {
KeyElement key;
DataElement data;
copyDataElements copy_data;
freeDataElements free_data;
copyKeyElements copy_key;
freeKeyElements free_key;
};
these are all the typedef used :
typedef struct Pair_t* Pair;
typedef enum PairResult_t {
PAIR_SUCCESS,
PAIR_OUT_OF_MEMORY,
PAIR_NULL_ARGUMENT,
} PairResult;
typedef void *DataElement;
typedef void *KeyElement;
typedef DataElement(*copyDataElements)(DataElement);
typedef KeyElement(*copyKeyElements)(KeyElement);
typedef void(*freeDataElements)(DataElement);
typedef void(*freeKeyElements)(KeyElement);
and a main function so that u could reproduce it
int main()
{
Pair pair;
for (int i = 1; i < 1000; ++i) {
char j = (char) i;
++j;
pair=pairCreate(&i,&j,copyDataChar,freeChar,copyKeyInt,freeInt);
pairDestroy(pair);
}
I added everything I could for a reproducible code
if anything should be edited please tell me in the comments
Pair pairCreate(...) {
...
pair->free_data = free_data;
pair->free_data = free_key;
// ^^^^^^^^^ UH OH
...
You owe me 15 mins of debugging time.

strdup non-dependent implementation (dumping malloc dependency)

I have a custom implementation for _strdup. It shouldn't have any dependencies, which means I cannot use CRT or anything built-in. The code below works fine. The only problem is that it depends on malloc. Therefore I can't use it with /NODEFAULTLIB, unless I implement my own malloc.
Any ideas for non-dependent implementations? Or at least a malloc/free implementation. I would even accept a shellcode implementation.
size_t __strlen(const char* str)
{
const char* s;
for (s = str; *s; ++s)
;
return (s - str);
}
void* __memcpy(void* to, const void* from, size_t count)
{
register char* f = (char*)from;
register char* t = (char*)to;
register size_t i = count;
while (i-- > 0)
*t++ = *f++;
return to;
}
char* __strdup(const char* str)
{
size_t len;
char* copy;
len = __strlen(str) + 1;
if (!(copy = (char*)malloc(len)))
return nullptr;
__memcpy(copy, str, len);
return copy;
}
I found a broken malloc implementation:
#define MEMORY_CAPACITY 20000
void* mov_sbrk(int increment)
{
static char global_mem[MEMORY_CAPACITY] = { 0 };
static char* p_break = global_mem;
char* const limit = global_mem + MEMORY_CAPACITY;
char* const original = p_break;
if (increment < global_mem - p_break || increment >= limit - p_break)
{
errno = ENOMEM;
return (void*)-1;
}
p_break += increment;
return original;
}
//=======================================================================
#define ALIGNMENT 8
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~(ALIGNMENT-1))
typedef struct list_t list_t;
struct list_t
{
unsigned in_use : 1; /* if the block is used or not */
size_t order; /* current order of block (2^order) */
list_t* succ; /* right child block in tree */
list_t* pred; /* left child block in tree */
};
#define K_MAX 22
#define K_MAX_SIZE (1 << K_MAX)
#define ORDER_0 4
// Size of the node metadata
#define META_SIZE (ALIGN(sizeof(list_t)))
static list_t* find_block(size_t);
static size_t get_order(size_t);
static list_t* split(list_t*, size_t);
/* Array of pointers to first block of order k at free_list[k] */
static list_t* freelist[K_MAX + 1];
static void* start = NULL;
static void print_freelist()
{
for (int i = ORDER_0; i <= K_MAX; i++)
{
int f = 0;
int j = 0;
list_t* current = freelist[i];
while (current)
{
if (!current->in_use)
{
f++;
}
j++;
current = current->succ;
}
}
}
void* malloc(size_t requested_size)
{
print_freelist();
if (requested_size <= 0)
{
return NULL;
}
if (!start)
{
// First allocation ever, grab memory and root the tree
start = mov_sbrk(K_MAX_SIZE);
list_t* top = reinterpret_cast<list_t*>(start);
top->order = K_MAX;
top->in_use = 0;
top->succ = NULL;
top->pred = NULL;
freelist[K_MAX] = top;
}
/* E.g. if requested size is 56 bytes, k = 6 (2^6=64)*/
size_t k = get_order(ALIGN(requested_size + META_SIZE));
list_t* r = find_block(k);
if (r) {
r->in_use = 1;
print_freelist();
return (r + 1);
}
else {
return NULL;
}
}
/* Find the smallest power of 2 larger than k */
static size_t get_order(size_t v)
{
int k = ORDER_0;
while ((1 << k) < v) {
k++;
}
return k;
}
// finds a suitable block of order k. if not found return null
static list_t* find_block(size_t k)
{
if (k > K_MAX)
return NULL;
list_t* current = freelist[k];
while (current) {
if (!current->in_use)
return current;
current = current->succ;
}
list_t* big_block = find_block(k + 1);
if (big_block) {
current = split(big_block, k);
}
return current;
}
static void remove_from_freelist(list_t* item)
{
size_t k = item->order;
if (freelist[k] == item)
freelist[k] = item->succ;
if (item->pred)
item->pred->succ = item->succ;
if (item->succ)
item->succ->pred = item->pred;
item->pred = NULL;
item->succ = NULL;
}
static void add_to_freelist(list_t* item)
{
size_t k = item->order;
if (!freelist[k])
{
freelist[k] = item;
item->succ = NULL;
item->pred = NULL;
return;
}
item->pred = NULL;
item->succ = freelist[k];
freelist[k]->pred = item;
freelist[k] = item;
}
static list_t* split(list_t* src, size_t new_order)
{
while (src->order > new_order)
{
/* src becomes left buddy */
remove_from_freelist(src);
// set new order
src->order = src->order - 1;
// calculate half size of old block, aka size of new order.
size_t size = 1 << src->order;
list_t* right = reinterpret_cast<list_t*>(src + size);
right->order = src->order;
right->in_use = 0;
add_to_freelist(right);
add_to_freelist(src);
}
return src;
}
static void merge(list_t* block)
{
if (block->in_use || block->order == K_MAX)
return;
list_t* buddy = (list_t*)((uint64_t)start + (block - start) ^ (1 << block->order));
if (buddy->in_use || buddy->order != block->order)
return;
list_t* left = block;
list_t* right = buddy;
if (block > buddy) {
left = buddy;
right = block;
}
remove_from_freelist(right);
remove_from_freelist(left);
left->order++;
add_to_freelist(left);
merge(left);
}
void free(void* ptr)
{
print_freelist();
if (!ptr)
return;
list_t* block = (((list_t*)ptr) - 1);
block->in_use = 0;
merge(block);
print_freelist();
}
void* calloc(size_t nbr_elements, size_t element_size)
{
size_t size = nbr_elements * element_size;
void* ptr = malloc(size);
if (ptr == NULL)
return NULL;
memset(ptr, 0, size);
return ptr;
}
void* realloc(void* ptr, size_t size)
{
if (!ptr) {
return malloc(size);
}
list_t* block = (((list_t*)ptr) - 1);
if ((1 << block->order) - META_SIZE >= size) {
return ptr;
}
void* new_ptr = malloc(size);
if (!new_ptr) {
return NULL;
}
memcpy(new_ptr, ptr, (1 << block->order) - META_SIZE);
free(ptr);
return new_ptr;
}
Since you have mentioned /nodefaultlib option, seems like you are on Windows. Then instead of using malloc() you can directly use Windows API function HeapAlloc() and then HeapFree() to free copy of the string later. You may want to wrap them into you own __malloc() and __free(), like this:
void* __malloc(size_t size)
{
return HeapAlloc(GetProcessHeap(), 0, size);
}
void __free(void* p)
{
if (p) HeapFree(GetProcessHeap(), 0, p);
}

How to see if a struct in struct pointer contains an element

I have a struct defined as:
typedef struct ltsaNode {
int call;
int action;
ltsaNode *nextActions;
ltsaNode *sibling;
} ltsaNode;
And a struct pointer *wanted and an int i
I want to check if any of the structs in wanted has call equal to i.
My current solution:
BOOL a = FALSE;
for(;wanted!= NULL;wanted->sibling)
{
if(wanted->call == i)
{
a=TRUE;
break;
}
}
Is there a better or faster way to do this ?
This is what you are looking for I guess.
BOOL a = FALSE;
for(; wanted != NULL; wanted = wanted->sibling)
{
if(wanted->call == i)
{
a = TRUE;
break;
}
}

Troubles with linked list - why aren't new elements being added to my list?

My linked list print function keeps printing only one value and I can't figure out why. Everything works as expected.
Here is the struct that I store in linked list:
typedef struct list_element {
int value;
struct list_element *next;
} list_element;
These are the functions to operate on list:
list_element createNewLinkedList()
{
list_element *myElement = (list_element *) malloc(sizeof(list_element));
myElement->value = 0;
myElement->next = NULL;
return *myElement;
}
int insertNewElementAtEndWithValue(list_element element, int value)
{
list_element *myElement = &element;
do {
if (myElement->next == NULL) {
list_element *new = (list_element *)malloc(sizeof(list_element));
new->value = value;
new->next = NULL;
myElement->next = new;
} else {
myElement = myElement->next;
}
} while (myElement->next != NULL);
}
int printListValues(list_element firstNode)
{
list_element *temp = &firstNode;
int sentinel = 1;
while (sentinel) {
printf(" %d,", temp->value);
if (temp->next != NULL) {
temp = temp->next;
} else {
sentinel = 0;
}
}
return 0;
}
And here is the function that prints only first value, 100:
void checkLinkedList()
{
list_element list = createNewLinkedList();
list.value = 100;
for (int i = 1; i < 10; i++) {
int value = rand();
insertNewElementAtEndWithValue(list, value);
}
printListValues(list);
}
What's wrong with that?
Your function
int insertNewElementAtEndWithValue(list_element element, int value)
is accepting a list_element object, meaning, a copy of the head of your list, what you want to pass is a pointer, so:
int insertNewElementAtEndWithValue(list_element *element, int value)
and this way you add the value to the actual list and not a copy of it.
You need to learn to use pointers, and use a debugger to check where your data stays.

Resources