I have a struct that has a BST of vertices within it (nodes called vertex). Each vertex has a char array name. I'm working on a function that gets all the vertex names and stores them in an array.
I feel like this should be working, but when testing I'm getting "memory clobbered past end of allocated block". I'm newer to C, and I've debugged a lot and can't surely determine which variable or where this is getting thrown. Any help would be appreciated!
I have narrowed it down so that I know this error is getting thrown somewhere in fill_vertices_array() once it is called from get_vertices(), but I can't narrow it down any more to a certain variable or recursion.
char **get_vertices(Graph graph) {
int num_verts = num_vertices(graph);
/* use a pointer so recursive calls won't effect incrementation */
int *i = malloc(sizeof(*i));
/* allocate space for all vertices plus 1 for the null index */
char **vertices = (char **)malloc((num_verts + 1) * sizeof(char *));
*i = 0;
/* fill with vertices */ /* CLOBBERING HAPPENING SOMEWHERE IN BELOW CALL */
fill_vertices_arr(vertices, i, graph.vertex);
/* save NULL as the last index */
vertices[num_verts] = NULL;
return vertices;
}
void fill_vertices_arr(char **vertices, int *start_index, Vertex *vertex) {
if (vertex != NULL) {
/* in-order traversal, adding to array */
fill_vertices_arr(vertices, start_index, vertex->left);
vertices[*start_index] = (char *)malloc(strlen(vertex->name) * sizeof(char));
strcpy(vertices[*start_index], vertex->name);
(*start_index) += 1;
fill_vertices_arr(vertices, start_index, vertex->right);
}
}
Note: In my test, I have added 8 vertices, and this has succeeded, so it has 8, each with a name. When I then run "char **names = get_vertices(graph)" I get the clobber error.
Related
I am trying to write a set of functions that will support a dynamically allocated array where a struct contains the array and other metadata. The goal is to return the function to the user, and the struct information can be called from a function. The code seems to work just fine until I get to the function to free the memory from heap. For reasons I do not understand, the code fails with a segmentation fault, which would indicate that the variable vec in the free_vector function is not pointing to the correct address. However, I have verified with print statements that it is pointing to the correct address. I am hoping someone can help me understand why the free_vector function is not working, specifically the free command. My code and implementation is shown below.
typedef struct
{
size_t allocated_length;
size_t active_length;
size_t num_bytes;
char *vector;
} Vector;
void *init_vector(size_t num_indices, size_t num_bytes) {
// Allocate memory for Vector struct
Vector *vec = malloc(sizeof(*vec));
vec->active_length = 0;
vec->num_bytes = num_bytes;
// Allocate heap memory for vector
void *ptr = malloc(num_bytes * num_indices);
if (ptr == NULL) {
printf("WARNING: Unable to allocate memory, exiting!\n");
return &vec->vector;
}
vec->allocated_length = num_indices;
vec->vector = ptr;
return &vec->vector;
}
// --------------------------------------------------------------------------------
int push_vector(void *vec, void *elements, size_t num_indices) {
Vector *a = get_vector_data(vec);
if(a->active_length + num_indices > a->allocated_length) {
printf("TRUE\n");
size_t size = (a->allocated_length + num_indices) * 2;
void *ptr = realloc(a->vector, size * a->num_bytes);
if (ptr == NULL) {
printf("WARNING: Unable to allocate memory, exiting!\n");
return 0;
}
a->vector = ptr;
a->allocated_length = size;
}
memcpy((char *)vec + a->active_length * a->num_bytes, elements,
num_indices * a->num_bytes);
a->active_length += num_indices;
return 1;
}
// --------------------------------------------------------------------------------
Vector *get_vector_data(void *vec) {
// - The Vector struct has three size_t variables that proceed the vector
// variable. These variables consume 24 bytes of daya. THe code below
// points backwards in memory by 24 bytes to the beginning of the Struct.
char *a = (char *)vec - 24;
return (Vector *)a;
}
// --------------------------------------------------------------------------------
void free_vector(void *vec) {
// Free all Vector struct elements
Vector *a = get_vector_data(vec);
// - This print statement shows that the variable is pointing to the
// correct data.
printf("%d\n" ((int *)vec)[2]);
// The function fails on the next line and I do not know why
free(a->vector);
a->vector = NULL;
a->allocated_length = 0;
a->active_length = 0;
a->num_bytes = 0;
}
int main() {
int *a = init_vector(3, sizeof(int));
int b[3] = {1, 2, 3};
push_vector(a, b, 3);
// The code begins to fails here
free_vector(a);
}
This program suffers from Undefined Behaviour.
The return value from init_vector is of type char **, a pointer-to-pointer-to-char,
return &vec->vector;
converted to void *.
In main, this value is converted to an int *
int *a = init_vector(3, sizeof(int));
This value is then converted back into a void * when passed to push_vector.
In push_vector, this value is cast to a char * in order to perform pointer arithmetic
memcpy((char *)vec + a->active_length * a->num_bytes, elements,
num_indices * a->num_bytes);
where this operation overwrites the original pointer returned by malloc contained in the vector member.
On my system, this attempts to write 12 bytes (three int) to memory starting with the position of the vector member in the Vector structure.
Vector *vec
| &vec->vector
| |
v v
+------+------+------+------+-----+
|size_t|size_t|size_t|char *|?????|
+------+------+------+------+-----+
This overflows, as sizeof (char *) is 8 on my system.
This is the wrong place to write data. The correct place to write data is *(char **) vec - or just a->vector.
If the write does not crash the program directly (UB), this surely results in free being passed a pointer value that was not returned by malloc, calloc, or realloc, or the pointer value NULL.
Aside: In free_vector, this value is also cast to an int *
printf("%d\n", ((int *)vec)[2]); /* added a missing semi-colon. */
Additionally, it is unclear if free_vector should free the original allocation, or just the vector member. You do go to lengths to zero-out the structure here.
Still, as is, you have a memory leak - albeit a small one.
void free_vector(void *vec) {
Vector *a = get_vector_data(vec);
/* ... */
free(a); /* This has to happen at some point. */
}
Note, you should be using offsetof to calculate the position of members within a structure. A static offset of 24 assumes two thing that may not hold true:
sizeof (size_t) is always 8 (actual minimum sizeof (size_t) is 2), and
the structure contains no padding to satisfy alignment (this seems likely given the form, but not strictly true).
The source you linked in the comments uses a flexible array member, not a pointer member, meaning the entirety of the data (allocation sizes and the vector) is stored in contiguous memory. That is why the & operator yields a valid location to copy data to in this implementation.
(Aside: the linked implementation appears to be broken by effectively using sizeof to get the base of the container structure from a pointer to the flexible array member (e.g., &((vector_container *) pointer_to_flexible_member)[-1]), which does not take into account the possibility of trailing padding, which would result in a larger offset than expected.)
Again with the memory allocation...
I don't seem to understand why my call to free is not working on the array in the object. It makes sense to me, but I get a segmentation fault. All I would like is to free the min_array and the array in the stack in the minStackFree function. Does anyone understand why this could be happening?
#include<stdio.h>
#include<stdlib.h>
typedef struct {
int * array;
int array_idx; // is 'top'
int * min_array;
int min_idx;
} MinStack;
MinStack * minStackCreate() {
MinStack * obj = malloc(sizeof(MinStack*));
//initialize the stacks
obj->array = malloc(10000*sizeof(int*));
obj->min_array = malloc(10000*sizeof(int*));
//initialize the index
obj->array_idx = -1;
obj->min_idx = -1;
}
void minStackFree(MinStack* obj) {
free(obj->min_array); // ************PROBLEM
free(obj->array); // ************PROBLEM
free(obj); // OK
}
It is not a matter of if malloc() will fail returning NULL, it is a matter of when. You must always validate EVERY allocation. Otherwise you risk Undefined Behavior (and likely a SegFault) if you fail to catch the allocation failure. A simple check is all that is needed, e.g.
#define ARRSZ 10000 /* if you need a constant, #define one (or more) */
MinStack *minStackCreate (void) {
MinStack *obj = malloc (sizeof *obj); /* use dereference pointer for typesize */
if (!obj) { /* validate EVERY allocation */
perror ("malloc-obj");
return NULL;
}
obj->array = malloc (ARRSZ * sizeof *obj->array); /* dereference pointer for typesize */
if (!obj->array) { /* validate EVERY allocation */
perror ("malloc-obj->array");
free (obj); /* free prior allocaitons */
return NULL;
}
obj->min_array = malloc (ARRSZ * sizeof *obj->min_array); /* ditto */
if (!obj->min_array) { /* ditto */
perror ("malloc-obj->min_array");
free (obj->array); /* free prior allocaitons */
free (obj);
return NULL;
}
//initialize the index
obj->array_idx = -1;
obj->min_idx = -1;
return obj; /* return allocated pointer */
}
As #chux-ReinstateMonica points out, with multiple allocations in your function, should an allocation fail, you must free the memory allocated in the function prior to the point of failure, before returning NULL to avoid a memory leak. Once NULL is returned, you would have no way to reach the allocations that occurred prior to the point of failure.
Don't use Magic-Numbers (e.g. 10000) in your code. If you need a constant, #define one, or use a global enum for the same purpose. That way if your needs change, you have one single location to update and the change is seen throughout your code.
Readability. The '*' dereference operator goes with the variable not the type. Why? Readability:
int* a, b, c;
most certainly does not declare 3-pointers to int, writing
int *a, b, c;
makes it abundantly clear that a single pointer to int and two integers are being declared.
Use the dereferenced pointer to set typesize. If you do that, you will never get the typesize wrong, e.g.
MinStack *obj = malloc (sizeof *obj);
and
obj->array = malloc (ARRSZ * sizeof *obj->array);
obj->min_array = malloc (ARRSZ * sizeof *obj->min_array);
While simple structs with the declaration in front of you may be easy to set the sizeof(type), when you are 1000 lines down in your code using complex types, things will not be so easy and it is easy to guess wrong.
With those changes, and returning obj on success or NULL on failure from minStackCreate() and the remainder compiles without warning.
It appears the issue was I needed to change:
MinStack * obj = malloc(sizeof(MinStack*));
//initialize the stacks
obj->array = malloc(10000*sizeof(int*));
obj->min_array = malloc(10000*sizeof(int*));
to
MinStack * obj = malloc(sizeof(MinStack));
//initialize the stacks
obj->array = malloc(10000*sizeof(int));
obj->min_array = malloc(10000*sizeof(int));
return obj;
Good morning!
I must handle a struct array (global variable) that simulates a list. In practice, every time I call a method, I have to increase the size of the array 1 and insert it into the new struct.
Since the array size is static, my idea is to use pointers like this:
The struct array is declared as a pointer to a second struct array.
Each time I call the increaseSize () method, the content of the old array is copied to a new n + 1 array.
The global array pointer is updated to point to a new array
In theory, the solution seems easy ... but I'm a noob of c. Where is that wrong?
struct task {
char title[50];
int execution;
int priority;
};
struct task tasks = *p;
int main() {
//he will call the increaseSize() somewhere...
}
void increaseSize(){
int dimension = (sizeof(*p) / sizeof(struct task));
struct task newTasks[dimension+1];
for(int i=0; i<dimension; i++){
newTasks[i] = *(p+i);
}
free(&p);
p = newTasks;
}
You mix up quite a lot here!
int dimension = (sizeof(*p) / sizeof(struct task));
p is a pointer, *p points to a struct task, so sizeof(*p) will be equal to sizeof(struct task), and dimension always will be 1...
You cannot use sizeof in this situation. You will have to store the size (number of elements) in a separate variable.
struct task newTasks[dimension+1];
This will create a new array, yes – but with scope local to the current function (so normally, it is allocated on the stack). This means that the array will be cleaned up again as soon as you leave your function.
What you need is creating the array on the heap. You need to use malloc function for (or calloc or realloc).
Additionally, I recomment not increasing the array by 1, but rather duplicating its size. You need to store the number of elements contained in then, too, though.
Putting all together:
struct task* p;
size_t count;
size_t capacity;
void initialize()
{
count = 0;
capacity = 16;
p = (struct task*) malloc(capacity * sizeof(struct task));
if(!p)
// malloc failed, appropriate error handling!
}
void increase()
{
size_t c = capacity * 2;
// realloc is very convenient here:
// if allocation is successful, it copies the old values
// to the new location and frees the old memory, so nothing
// so nothing to worry about except for allocation failure
struct task* pp = realloc(p, c * sizeof(struct task));
if(pp)
{
p = pp;
capacity = c;
}
// else: apprpriate error handling
}
Finally, as completion:
void push_back(struct task t)
{
if(count == capacity)
increase();
p[count++] = t;
}
Removing elements is left to you – you'd have to copy the subsequent elements all to one position less and then decrease count.
how can i define an array in c which works like vector? This array should take any amount of values. It can take 0 values or 10 values or 100 values.
The code below works but gives me a runtime error that stack was corrupted.
int i = 0;
int* aPtr = &i;
int* head = aPtr;
for(i=0;i<6;i++){
(*aPtr)=i;
aPtr++;
}
Similarly how can i use char* str to take any amount of characters followed by null character in end to make a string?
Practice for interviews :)
There are many ways to do this in C, depending on your requirements, but you said "any number of values" (which usually means as many as will fit in memory). That's commonly done using realloc to grow the size of an array dynamically. You'll need to keep some bookkeeping information too on the size of the array as it grows.
void
store (vector_t * v, int idx, int value)
{
if (v->size < idx) {
v->size = idx * 2;
v->data = realloc(v->data, v->size);
}
v->data[idx] = value;
}
This being tagged "homework", I've left some details to fill in such as the definition of vector_t.
In Your for loop , after the first iteration, you are trying to access aPtr which points to a memory location which was not declared or reserved before. In the first iteration, the int i did the memory allocation for you.
What you could do though would be to initally allocate the memory required using malloc .
Once this memory is allocated , and if you walk through only the allocated stack space, you wont come across a run time error.
PS:Your code does not work if it just compiles. Any program may contain run time as well as compile time errors. Your code sample is a very common example of run-time error.
This isn't too difficult. The important thing to remember is that you will need to initially allocate memory for your array using malloc(...) or calloc(...). After that you can easily allocate (or deallocate) memory as items are added or removed. The method for dynamically adding or removing memory (which is used to store the items in the array) is realloc(...). The wiki page for C Dynamic Memory Allocation is actually pretty informative. I've provided an example below showing how to initially allocate a char* array, then increase the size and decrease the size.
#include "stdio.h"
#include "stdlib.h"
int main()
{
char *myDynamicString;
/* allocate initial memory */
myDynamicString = (char *)malloc(sizeof(char) * 2);
myDynamicString[1] = '\0';
/* set values */
myDynamicString[0] = 'A';
/* prints: A */
printf("String: %s\n", myDynamicString);
/* make string bigger */
myDynamicString = (char *)realloc(myDynamicString, sizeof(char) * 6);
myDynamicString[5] = '\0';
/* set values */
myDynamicString[1] = 'P';
myDynamicString[2] = 'P';
myDynamicString[3] = 'L';
myDynamicString[4] = 'E';
/* prints: APPLE */
printf("Bigger String: %s\n", myDynamicString);
/* make string smaller */
myDynamicString = (char *)realloc(myDynamicString, sizeof(char) * 3);
myDynamicString[2] = '\0';
/* set values */
myDynamicString[1] = 'Z';
/* prints: AZ */
printf("Smaller String: %s\n", myDynamicString);
/* don't forget to release the memory */
free(myDynamicString);
return 0;
}
I am using the linked list example from junghans and try to make it work
with some server code. In the char array, I could insert a host (from inet_ntoa)
and update it's age. So I can send one packet to the daemon, but then it crashes.
I tried setting next_pointer=start_pointer; because from what I read, it will be
a circular list. However, after receiving the second packet, strcpy crashes..
Questions:
How do I point to the beginning, if next_pointer=start_pointer doesn't do the trick?
Do I need to free, before overwrite a member of the char array?
struct x {
char name[20];
int age;
struct x *next_rec;
};
struct x *start_pointer;
struct x *next_pointer; // starting hosts, will be overwritten
char *names[] = {
"127.0.0.1",
"evil666",
"192.168.56.101",
""
};
int ages[] = {0,20,30,0};
// some other code
while (1) {
sleep(1);
us=time(NULL);
printf("%ld, Sleep a second\n", us);
buf[0] = 0x0;
current_host = 0x0;
memset (buf,0,sizeof buf);
if(recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*)&si_other, &slen)==-1)
diep("recvfrom()");
current_host = inet_ntoa(si_other.sin_addr);
if(!current_host)
diep("inet_ntoa()");
/* linked list initialization */
/* Initalise 'start_pointer' by reserving
* memory and pointing to it
*/
start_pointer=(struct x *) malloc (sizeof (struct x));
if(!start_pointer)
diep("start pointer on holiday");
/* Initalise 'next_pointer' to point
* to the same location.
*/
next_pointer=start_pointer;
/* Put some data into the reserved
* memory.
*/
strcpy(next_pointer->name,current_host);
next_pointer->age = ages[count];
/* Loop until all data has been read */
while ( ages[++count] != 0 )
{
/* Reserve more memory and point to it */
next_pointer->next_rec=(struct x *) malloc (sizeof (struct x));
if(!next_pointer)
diep("next pointer on holiday");
strcpy(next_pointer->name, names[count]);
next_pointer->age = ages[count];
}
next_pointer->next_rec=NULL;
next_pointer=start_pointer;
/* insert new record, update age */
while (next_pointer != NULL)
{
printf("%s ", next_pointer->name);
if(strstr(next_pointer->name,current_host)) {
printf("%d \n", next_pointer->age+1);
}
if(!strstr(next_pointer->name,current_host)) {
printf("%d \n", next_pointer->age);
}
next_pointer=next_pointer->next_rec;
}
next_pointer=start_pointer; // XXX
The problem with your code is that you missed this part from the linked C file in the init loop: next_pointer=next_pointer->next_rec. As a result, in first iteration you allocate new list node, but then modify contents of the first node. And then in subsequent iterations you allocate even more nodes, but you still only modify the first node.
Then right after the loop you terminate the list, but since you did not update next_pointer in the meantime, you're list has now a single node. (And you leaked some memory there, overwriting addresses with next allocations and NULL, so now you cannot free it.)
As to your more specific questions:
Question 1: next_pointer is only a helper variable to iterate over a list. If you want a circular list, you should set some next_rec pointer to start_pointer. You could do it like this:
for (next_pointer = start_pointer;
next_pointer->next_rec != NULL; /* This is not the last node. */
next_pointer = next_pointer->next_rec /* Move to the next node. */)
;
/* At this moment next_pointer points to the last node of the list. */
next_pointer->next_rec = start_pointer; /* And a cycle is there. */
However, you can actually do this while initialising your loop. When you exit from the init loop, next_pointer is indeed pointing at the last node. So instead of doing next_pointer->next_rec=NULL to terminate the list, do next_pointer->next_rec = start_pointer to make a cycle.
UPDATE That is, if you do want a circular list. Because in fact next_pointer=start_pointer will make next_pointer point at the beginning. So I assumed you want the end of the list point to the beginning (as you mentioned circular list).
Question 2: If you didn't allocate a string, explicitly (with malloc) or implicitly (for example with strdup), you don't need to free it. In particular in that code there are no strings to free:
next_pointer->name is an array within structure. You allocated it along with the structure (list node), and it will be freed with the node.
names is an array of pointers to the constant strings. They were not allocated, but instead will be part of data section of application compiled code, and thus cannot be freed.
Last but not least: lookout for strcpy. If you are copying only IPs there, 20 characters will always be enough, but the first moment you'll try to copy something larger, you have buffer overflow and can overwrite some other data. You should be using strncpy, with n = 19, followed by next_pointer->name[19] = 0 to ensure null termination.
And you don't need to run strstr() twice there. It either returns NULL pointer or not, so you could run
if (strstr( /* .. the arguments .. */ )) {
/* ... */
} else {
/* what if the call did return NULL. */
}