During my stack building I encountered a problem with free an element inside an array in my Pop function.
This is the code:
Element Pop(Stack *stackPtr)
{
Element temp = stackPtr->content[stackPtr->size-1];
Element* newE = (Element*)realloc(stackPtr->content,(stackPtr->size-1)*sizeof(Element));
free(stackPtr->content[stackPtr->size-1]);
stackPtr->content=newE;
stackPtr->size--;
return temp;
}
And for some reason the free(stackPtr->content[stackPtr->size-1]); do an error every time.
Why is that and how do I fix that?
Thanks.
This is the whole code:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
int kind; // boolean
int num;
char ch;
} Element;
typedef struct
{
Element *content;
int size;
} Stack;
void Init(Stack* stackPtr)
{
stackPtr->content = (Element*)malloc(1*sizeof(Element));
stackPtr->content[0].kind = 3;
stackPtr->content[0].ch = 'a';
stackPtr->content[0].num = -2;
stackPtr->size = 1;
}
void Push(Stack* stackPtr, Element element)
{
stackPtr->content = (Element*)realloc(stackPtr->content,((stackPtr->size)+1)*sizeof(Element));
stackPtr->size++;
stackPtr->content[stackPtr->size-1] = element;
}
Element Pop(Stack *stackPtr)
{
Element temp = stackPtr->content[stackPtr->size-1];
Element* newE = (Element*)realloc(stackPtr->content,(stackPtr->size-1)*sizeof(Element*));
free(stackPtr->content[stackPtr->size-1]);
stackPtr->content=newE;
stackPtr->size--;
return temp;
}
Element Top(Stack *stackPtr)
{
return stackPtr->content[stackPtr->size-1];
}
Of course this crashes - you just have reallocated the data which stackPtr->content was pointing to, so the array access is now invalid.
Since you already reallocated, and you are returning the removed element, that call to free is pointless though, and illegal in multiple ways. The memory is already free'd, but not only that, it was never a pointer to begin with.
Also be aware which parameters to realloc are valid. If your Pop function "removes" the last element, you would try to realloc to a size of zero, which isn't legal.
And you should put in a defensive check anyway, ensure that nobody is trying to pop from an already empty stack.
Since content[] is an array of pointers, the realloc should use sizeof(Element*), not sizeof(Element), especially if sizeof(Element) less than sizeof(*).
Edited to reflect intent of Comments:
Element *Pop(Stack *stackPtr)
{
if (stackPtr->size==0) return NULL;
Element temp = stackPtr->content[stackPtr->size-1];
stackPtr->size--;
if (stackPtr->size==0) free(stackPtr->content)
else {
Element* newE = (Element*)realloc(stackPtr->content,stackPtr->size)*sizeof(Element));
stackPtr->content=newE;
}
Element* rslt = malloc(sizeof(Element);
memcpy(rslt,&temp,sizeof(Element));
return rslt;
}
In the using code the pointer returned would need to be free'd separately. I view this as safer than assuming the compiler will copy the auto allocation of temp into the return value, anyways.
Related
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* create_int_array(){
int* arr;
arr = (int *)calloc(1,sizeof(int));
return arr;
}
char** create_string_array(){
char** arr = calloc(1,sizeof(char));
return arr;
}
void append_int(int* array, int element, int index){
array = (array+index);
*array = element;
}
void append_string(char** array , char* element,int index){
*(array + index) = calloc(1,sizeof(char*));
strcpy(*(array + index),element);
}
void delete_string(char** array, int index){
free(array[index]);
}
void delete_int(int* array,int index){
array[index] = NULL;
}
/////// M A I N F I L E ///////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "basic_data_file.h"
int main(int argc, char const *argv[])
{
/* code */
char **array;
array = create_string_array();
char *full_name = calloc(strlen("hamza arslan"),sizeof(char*));
strcpy(full_name,"hamza arslan");
char* mail = calloc(strlen("test#gmail.com"),sizeof(char*));
strcpy(mail,"test#gmail.com");
char* address = calloc(strlen("Hacettepe Universty"),sizeof(char*));
strcpy(address,"Hacettepe Universty");
char* statu = calloc(strlen("student"),sizeof(char*));
strcpy(statu,"student");
append_string(array,full_name,0);
append_string(array,mail,1);
append_string(array,address,2);
append_string(array,statu,4);
for(int i=0; i< 3; i++){
printf("%s\n",array[i]);
free(array[i]); // get free double pointer
}
printf("%s\n",array[4]); // because index 3 blow up
free(full_name);
free(mail);
free(address);
free(statu);
return 0;
}
I was try to own my basic array library . As you know else in some languages have high level array types. They are making easy our stocking operation. But in c, it's more complicated especially about string. I have 2 problem in here . First of all , when i give index=3 in append_string function , code blow up with Aborted(core dumped) error.(./run': double free or corruption (out)). Secondly , when i was checking leak memory ,it's get memory leak even i use free. What can i do?
Your create_xy_array functions allocate an array of 1 element, and they stay that way until the very end. When you have a one-element array and index, read/write its second and further elements, C itself happily approves, but the result will not work, it silently destroys everything in its path.
First of all, for having a dynamic array, you have to track its length yourself, C allocations/arrays do not know their own size. So you need a struct, containing the length and a pointer, something like
typedef struct IntArray {
int length;
int *elements;
} IntArray;
Then allocate it, for 0 elements, as there is nothing inside at the beginning:
IntArray* create_int_array() {
IntArray* ret = (IntArray*) malloc(sizeof(IntArray));
ret->length = 0;
ret->elements = NULL;
return ret;
}
void free_int_array(IntArray* arr) {
free(arr->elements);
free(arr);
}
Then you can try putting something inside:
void append_int(IntArray* arr, int element) {
arr->length++;
arr->elements = (int*) realloc(arr->elements, arr->length*sizeof(int));
arr->elements[length-1] = element;
}
(appending means adding something to the end of an array, there is no need for indices here)
And this could go on forever, deletion of an arbitrary element should shift the "upper" part of the array (memcpy) and resize the result to one element smaller or you could track the capacity of the array, which can be larger than its current length (but then it has to be incorporated into the append function and probably others).
(Disclaimer: I hope the snippet is correct, but I do not use C too often - and I can not suggest a good tutorial for the same reason, but that is what you probably need)
Note: I haven't code in C for years and I haven't check the code so double check and let me know.
Based on your description, you are trying to do a Vector.
Therefore, there are different ways that you can handle this.
Approach 1:
Create a structure which will hold the array, the capacity of the array, and the size of the array.
typedef struct StrArray{
int capacity;
int size;
int *integers;
}
The trick here is to take attention when you increase/decrease the capacity.
If you increase the capacity above the size of the array, then:
You need to create a new array with double the capacity
Copy all elements to the new array
Change pointer to new array
Free the memory of the old array
Approach 2
You can extend the previous approach by creating a function which returns a struct which holds the storage plus function pointers to the methods you wish to implement.
typedef struct StrStorage{
int capacity;
int size;
int *integers;
} StrStorage;
typedef struct StrArray {
StrStorage storage;
int (*capacity)(StrArray*);
int (*size)(StrArray*);
StrArray *(*append)(StrArray*, int);
void (*increaseStorage)(StrArray*);
// Add other methods here
} StrArray;
int capacity(StrArray *self) {
return self->storage->capacity;
}
int size(StrArray *self) {
return self->storage->size;
}
StrArray *append(StrArray *self, int integer){
if ((self->capacity() + 1) > self->size()){
self->increaseStorage();
}
// The rest of the magic goes here
return self;
}
StrArray *initializeStrArray(int n) {
StrArray* strArray = malloc(sizeof(StrArray));
strArray->chars = malloc(sizeof(char) * n);
strArray->capacity= capacity;
strArray->append = append;
return strArray;
}
Approach 3:
This approach is a continuation of the previous one.
In order to reduce the memory allocation, you can create an equivalent to a singleton which holds all the manipulation functions and then assi
There will be several crashes, but here is one:
char** arr = calloc(1,sizeof(char));
You are allocating 1 byte which is not sufficient to store a (char *), which needs between 2 and 8 bytes depending on the OS and target machine.
Try this instead:
char** arr = calloc(1,sizeof(char*));
You should double-check each line of code. C is not a forgiving language - mistakes are severely punished.
I'm trying to make an Linked List that essentially holds a string (rather than a character array). I keep getting segmentation fault (core dumped) and I'm not sure where/how I'm allocating memory wrong
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystring
{
char letter;
int size;
int isHead;
struct mystring*next;
};
struct mystring * create_empty_string(int size)
{
struct mystring * string = malloc(sizeof(struct mystring));
string->size = size;
string->isHead = 0;
return string
}
struct mystring * make_string(struct mystring * list,char * string)
{
for(int i = 0 ; i < strlen(string) ; i++)
{
list->letter= string[i];
list = list->next;
}
return list;
}
void printList(struct mystring* list) {
//start from the beginning
while(list->letter != '\0') {
printf("(%c) ",list->letter);
list = list->next;
}
}
int main()
{
struct mystring * string = create_empty_string(10);
string = make_string(string, "hey");
printList(string);
}
When letter is defined as char letter; and your compiler allows you to do string->letter = malloc(sizeof(char)); without complaining, this means that you are trying to compile without the slightest bit of warnings enabled. You are not going to go very far like that. Figure out how to enable all warnings on your compiler, then perhaps work on the warnings a bit to disable the really annoying ones, and from that moment on your compiler will be helping you to avoid doing such nonsensical things as assigning the result of malloc() to a char.
As noted, your create_empty_string() function is poorly constructed. I suggest building the linked list one node at a time by feeding individual characters into a function called append_to_string() or similar, which will create a new node and link it to the previously constructed list (or become the list itself if it's the first node).
I need to allocate memory to an array inside my struct, this array has no defined size at the beginning when i define the struct:
typedef struct stacks {
int size; // Stores the size of my -values- array
int sp; //points to the top of the stack, my stackpointer
int *values;
} STACKS;
So, to initialize my struct i wrote this function, that allocates (using calloc?) memory to my array, and i put inside SIZE variable, the new size of my array .
#define MAXIMUM 10
int initStacks(STACKS *s){
s->values = calloc(MAXIMUM,sizeof(int));
s->size = MAXIMUM;
s->sp = 0;
return 0;
}
Now, if i want to push something to the top of the stack (LIFO) i use this:
int pushs(STACKS *s, int x){
if (s->sp==s->size) {
realloc(s->values, MAXIMUM * sizeof(int));
s->size*=2;
}
s->values[s->sp]=x;
s->sp++;
}
Is this the correct way of doing this?
Is realloc working as it should in my function?
Thank you very much for your help!
EDIT:
would this make more sense? This way, i really don't need to declare the value of the array, being that defined with #define maximum 10
typedef struct stacks {
int size; // guarda o tamanho do array valores
int sp;
int *values;
} STACKS;
int initStacks(STACKS *s){
s->values = calloc(1,sizeof(int));
s->size = 1;
s->sp = 0;
return 0;
}
int isEmptys(STACKS *s){
return((s->sp)==0);
}
int pushs(STACKS *s, int x){
s->size++;
realloc(s->values, s->size * sizeof(int));
s->values[s->sp]=x;
s->sp++;
}
Assuming you have an original size factor (the name capacity would be as-appropriate, if not more so), your original code lacks several things:
Compares the size against a constant, rather than the current sp against the stack current size.
Does not save nor test the return result of realloc
Does not actually double the allocation (you're missing the 2x in the realloc expression.
Declares an int return result, but no such return exists.
Has no way of communicating back to the caller the push result (success or not). That missing return result would be ideal for this, btw.
Addressing all of these:
int pushs(STACKS *s, int x)
{
if (s->sp == s->size)
{
void *pv = realloc(s->values, 2 * s->size * sizeof *(s->values));
if (pv != NULL)
{
s->values = pv;
s->size *= 2;
}
else
{
fprintf(stderr, "Failed to resize stack\n");
return -1;
}
}
s->values[s->sp++] = x;
return 0;
}
Untested, but hopefully close enough.
Best of luck
Although not directly an answer to the actual question, but more to the general problem, I post this as it does not fit into a comment.
If you expect excessive push/pop operations and memory usage, the following might be an alternative:
typedef struct SubStack_s {
struct SubStack_s *prev;
int data[ENTRIES_PER_SEGMENT];
} SubStack;
typedef struct {
SubStack *tos; // init to NULL
size_t sp; // init to 0
} Stack;
The basic idea is to push elements onto each substack until full (as you already do). If the current one is full, you alloc a new one, chain them (new->prev = old) and continue with the new one (storing new to Stack.tos)
Pop works similar, free'ing each substack once it is not used anymore.
That concept is called "fragmented stack". It is much more efficient than the realloc-approach (it avoids copying) and does not fragment RAM as all block are of equal size. Oh, and it allows to have pointers into the stack, which the realloc-varaint does not, because the address of the stack can change.
I have a struct called menu_item that looks like:
struct menu_item
{
char name[ITEM_NAME_LEN+1];
};
And in main I declare an array of pointers to the struct (am I right about this part?):
struct menu_item * menu_items[NUM_MENU_ITEMS];
And also in main I'm trying to call:
init_menu(&menu_items[NUM_MENU_ITEMS]);
init_menu function looks like this:
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
However I'm getting a segmentation error, what am I doing wrong? Thanks in advance.
Take a closer look to your function.
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
You need to carry the size of the array in a second parameter in your function. However, NUM_MENU_ITEMS, seems to be a global #define, thus you don't need to carry a second parameter.
Then you are accessing an out of bound cell, menu_items[NUM_MENU_ITEMS]. I assume you know that the indexing starts from 0 and ends at NUM_MENU_ITEMS-1.
In your function, you need, inside a loop, to allocate memory. Moreover, you don't need to cast what malloc returns.
So, for example, you could do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ITEM_NAME_LEN 15
#define NUM_MENU_ITEMS 3
// Define the struct before main
struct menu_item {
char name[ITEM_NAME_LEN + 1];
};
// Give a synonym. Now struct menu_item is the same with menu_item_t.
// Notice the _t extension, which implies that this is a typedef.
typedef struct menu_item menu_item_t;
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), allocate memory for
* every cell of the array.
*/
void init_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// for every cell of our array, allocate memory
p[i] = malloc(sizeof(menu_item_t));
// check that allocation for the i-th cell is OK
if(!p[i]) {
printf("Error in allocating %d item!\n\n", i);
return;
}
}
}
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), de-allocate memory for
* every cell of the array.
*/
void delete_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// free the memory we had allocated for the i-th cell
free(p[i]);
// set the pointer to NULL
p[i] = NULL;
}
}
void fill(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
strcpy(p[i]->name, "myitem");
}
}
void print(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
printf("%s\n", p[i]->name);
}
}
int main(void) {
// Declare an array of pointers of menu_items_t.
// The size of the array is NUM_MENU_ITEMS
menu_item_t *menu_items[NUM_MENU_ITEMS];
init_menu(menu_items);
fill(menu_items);
print(menu_items);
delete_menu(menu_items);
return 0;
}
When I deal with structs, I always have this example on mind.
You are calling your function as
init_menu(&menu_items[NUM_MENU_ITEMS]);
This does not make sense. Expression &menu_items[NUM_MENU_ITEMS] creates a pointer to element with index NUM_MENU_ITEMS. Such element does not exist. Your array has elements numbered from 0 to NUM_MENU_ITEMS - 1. There's no element with index NUM_MENU_ITEMS.
Expression &menu_items[NUM_MENU_ITEMS] produces a pointer into the uncharted memory past the end of the array. You pass that pointer to the function. Later you are trying to use that pointer as if it were your array. You write into that uncharted memory, which causes a crash.
If you want to pass your array to the function, just pass it. Your function should be called as
init_menu(menu_items);
That's it. There's no need to create any pointers to any elements with strange indices.
Later, inside your function you are again trying to access element NUM_MENU_ITEMS of your array
menu_items[NUM_MENU_ITEMS] = ...
This does not make sense either for the very same reasons.
I am trying to have dynamically allocate arrays of structures and perform operations on them but i keep running into segmentation faults. could someone help me out?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *malloc(size_t size);
typedef struct {
double x;
double y;
} coords;
struct figure {
char fig_name[128];
int coordcount, size_tracker;
coords *pointer;
} fig;
void init_fig(int n, struct figure **point)
{
printf("%u\n", sizeof(coords));
point[n]->pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n]->pointer == NULL){
exit(-1);
}
point[n]->pointer[19].x = 2;
point[n]->pointer[0].x = 1;
point[n]->pointer[0].y = 2;
point[n]->pointer[7].x = 100;
}
int main()
{
int numfigs = 1;
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
point = &fig;
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
I labelled where the first seg fault occurs, (used ddd). what i dont get is that i can manipulate point[1] in main but not in any other function.
I agree with #Maxim Skurydin.
Nevertheless I'd like to explain your mistake in some more details.
Reading your init_fig one assumes that the parameter you pass struct figure **point - is actually array of pointers to struct figure. And this function accesses its n'th element.
However in your main you do something else. You allocate an array of struct figure, and your point variable points to its head. Then you take the address of this local variable and call your init_fig.
Here's the problem. init_fig assumes that you pass it an array of pointers, whereas actually this "array" consists of a single element only: the local point variable declared in main.
EDIT:
How to do this properly.
Leave main intact, fix init_fig.
This means that actually there's an array of figure structs. Means - a single memory block, interpreted as an array of consequent structs.
void init_fig(int n, struct figure *point)
{
printf("%u\n", sizeof(coords));
point[n].pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n].pointer == NULL){
exit(-1);
}
point[n].pointer[19].x = 2;
point[n].pointer[0].x = 1;
point[n].pointer[0].y = 2;
point[n].pointer[7].x = 100;
}
Leave init_fig intact. Fix main.
This means that we actually should allocate an array of pointers, every such a pointer should point to an allocated point structure.
int main()
{
int numfigs = 1;
struct figure ** point;
point = malloc(sizeof(struct figure*) * 16);
for (i = 0; i < 16; i++)
point[i] = malloc(sizeof(struct figure));
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
You allocate memory and store the pointer in point but then you forget that pointer when you assign &fig to it.
point = malloc(sizeof(struct figure) * 16);
point = &fig;
So, you are essentially trying to write fig[1], that does not make sense.
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
here point is pointer pointing to memory of 16 structures in heap
but in the next line you have done this
point = &fig;
so its memory leak and also point is not pointing to that allocated region anymore
and also init_fig should be like this
void init_fig(int n, struct figure **point)
It's the problem of segfault
Eliminate this line point = &fig;
and modify the function:
void init_fig(int n, struct figure *point)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
...
}
since you should pass an array of structs and not an array of pointers.
Also, add a third parameter to the init_fig function so you can pass the size of the array of points that you want to create. Like :
void init_fig(int n, struct figure *point, int size)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * size);
...
}
Therefore, making the function more reusable.
Modify also the call to that function:
init_fig(numfigs, &point); to init_fig(numfigs, point);