Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
So, this is working fine... that means, no compiler errors, it seems that there is no memory leak and it is doing what I wanted it to do. That said should it be working? When I go to books_init I send a local variable to collection, doesn't it mean that when I go back to main it shouldn't be working? (or undefined behavior?). Also, in case you say that I have to malloc it, do I have to free it after? (commented on cleanup)
/* pseudo struct Collection{
size_t size, capacity;
Volume *volumes;
} */
void collection_init(Collection *col, size_t capacity){
col->size = 0;
col->capacity = capacity;
col->volumes = malloc(sizeof(Volume) * capacity);
}
void collection_resize(Collection *col, size_t capacity){
Volume *v = realloc(col->volumes, capacity * sizeof(Volume));
if(!v) return;
col->capacity = capacity;
col->volumes = v;
}
void collection_add(Collection *col, Volume *volume){
if(col->size >= col->capacity)
collection_resize(col, col->capacity * 2);
col->volumes[col->size++] = *volume;
}
void collection_clean(Collection *col){
//for(vol : col->vol) free(vol);
//should I free every element or just volumes?
free(col->volumes);
}
void books_init(Collection *col){
for(int i = 0; i < 25; ++i){
Volume v = {.swag = i};
collection_add(col, &v);
}
}
int main(){
Collection col;
collection_init(&col, 10);
books_init(&col);
for(int i = 0; i < col.size; ++i){
printf("\tVol[%d].id = %d\n", i, col.volumes[i].swag);
}
collection_clean(&col);
return 0;
}
Thanks for your time
This line in books_init
Volume v = {.swag = i};
creates a local variable called v with member swag initialized to i. The address of that variable is then passed to collection_add. That is allowed because v is still in scope.
This line in collection_add
col->volumes[col->size++] = *volume;
makes a copy of the contents of the Volume structure, and stores that copy in the memory that was allocated in collection_init.
After collection_add returns, the variable v in books_init goes out of scope, but that's OK because the contents of v were copied and saved in the memory that col->volumes points to.
When the program ends, collection_clean only needs
free(col->volumes);
to remove all of the Volume copies from memory.
The only flaw I see in your program occurs if realloc fails. In that case, you still write to the Volume array. This will cause a buffer overrun and memory corruption. To avoid this, the collection_add function should verify that the collection_resize function succeeded before performing the copy. For example, you could check again that col->capacity > col->size before doing the copy.
TL;DR your code is fine as long as the realloc always succeeds.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I tried to create my own malloc function in C, using array as the memory i'll be working with. But when the remaining memory size surpasses a certain number of bits, the program crashes saying " Exception thrown: write access violation."
I divide the memory to a blocks. Each block will have a little metadata block that preserves the size of the block and whether is it free or taken (at the beginning, the entire memory array is one big block).
Then my malloc finds the first memory block with sufficient size and uses it (or part of it).
The problem is:
If i initialize an array of size 20000 bytes for example, my malloc will only work if the remaining free bytes in array would be 17708 or more.
#include <stdio.h>
char memory[20000];
struct block {
unsigned int size;
int free;
struct block* next;
};
struct block* freeList = (void*)memory;
void initialize() { /
freeList->size = 20000 - sizeof(struct block);
freeList->free = 1;
freeList->next = NULL;
}
void split(struct block* fitting_slot, unsigned int size) {
struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
unsigned int temp = (fitting_slot->size) - size - sizeof(struct block);
printf("Remaining memory size is %d\n", temp);
new->size = temp; // this is where program crashes
new->free = 1;
new->next = fitting_slot->next;
fitting_slot->size = size;
fitting_slot->free = 0;
fitting_slot->next = new;
}
void* MyMalloc(unsigned int noOfBytes) {
struct block* curr;
void* result;
if (!(freeList->size)) {
initialize();
}
curr = freeList;
while ((((curr->size) < (noOfBytes + sizeof(struct block))) || ((curr->free) == 0)) && (curr->next != NULL)) {
curr = curr->next;
}
printf("From the free memory of size : %d\n", curr->size);
printf("We will occupy this size : %d\n", noOfBytes + sizeof(struct block));
if ((curr->size) == (noOfBytes + sizeof(struct block))) {
curr->free = 0;
result = (void*)(++curr);
printf("Exact fitting block allocated\n\n");
}
else if ((curr->size) > (noOfBytes + sizeof(struct block))) {
split(curr, noOfBytes);
result = (void*)(++curr);
printf("Fitting block allocated with a split\n\n");
}
else {
result = NULL;
printf("Sorry. No sufficient memory to allocate\n\n");
}
return result;
}
int main(){
unsigned int size = 2270 * sizeof(char);
char* k = (char)MyMalloc(size);
printf("Success\n");
}
If the number of "size" is 2269 or lower, program works correctly.
If the number of "size" in main is 2270 or higher, program crashes on the line
new->size = temp in function split() saying "Exception thrown: write access violation."
OK, so I think you are offsetting by the wrong amount. Pointers in C have an indication of the size of thing they are pointing to, so if you want a byte offset you need to cast the pointer to char*, or I think void* should also work fine. (see the edit below, this was mistaken)
I have not done a detailed debug, however changing line 20 from
struct block* new = (void*)(fitting_slot + size + sizeof(struct block));
to:
struct block* new = (void*)(fitting_slot) + size + sizeof(struct block);
seemed to at least stop the errors.
I can set size right up to 19968 (the max) and all seems well.
EDIT
So, as #R.. correctly pointed out below, arithmatic on void pointers is not allowed (although gcc and probably other compilers let you get away with it) - see this answer, for example, on the topic.
The most appropriate thing would seem to be casting to char*. Given that the fitting_slot variable is also already in units of the block size, rather than adding sizeof(struct block) it is simpler to just add 1 to that, then the size once case to char:
struct block* new = (void*)((char*)(fitting_slot+1) + size);
I've tested this and it seems to work the same in gcc as the previous edit, but legally now.
In the line where new is assigned pointer arithmetic is done on a struct block*.
When you do pinter arithmetic on a typed pointer, c semantics assumes, that an array is being manipulated. For example ptr++ on a struct block* increases the value of the pointer by sizeof(struct block).
You should cast your pointer to char* before performing arithmetic on it this way. I am not sure I got everything, but I hope this can get you started.
I used my debugger.I assume that you forgot a malloc in split function.
struct block* new = (void*)malloc(fitting_slot + size + sizeof(struct block));
If you use a debbuger you'll find out that new->size was unreachable address.
**this would be line 20, if the include is in line 1.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
TASK: Let's say there is an integer stack S with M elements. Give the algorithm that will remove all those numbers from stack S that appear two or more times. (write the task using C/C++)
NOTE: We are not allowed to use std::stack to solve this task.
First of all I decided to use C language, and this is stack implementation I use.
int* stack = (int*)malloc(10 * sizeof(int));
int size = 10;
int sp = -1;
bool isempty() {
return (sp == -1);
}
bool isfull() {
return (sp == size - 1);
}
void push(int x) {
if (isfull()) {
printf("Full!");
}
else {
sp++;
stack[sp] = x;
}
}
int pop() {
int x;
if (isempty()) {
printf("Empty!");
}
else {
x = stack[sp];
sp--;
}
return x;
}
void peek() {
if (!isempty()) {
printf("%d", stack[sp]);
}
}
void clear() {
while (!isempty()) {
pop();
}
}
void print() {
if (!isempty()) {
for (int i = 0; i < sp+1; i++) {
printf("%d ", stack[i]);
}
}
printf("\n");
}
My idea of solving this task was to make another temp stack and copy main stack into it, than use two for loops to compare all elements and inside that I used if statment to check if they are same or not, if they are not same I just pushed them into back into stack that was previously cleared, by this way I'm supposed to skip all duplicate elements but for some reason this code is not working properly it keeps spamming me "Full!" message.
void removeDuplicates() {
int* temp = (int*)malloc(10 * sizeof(int));
int temp_size = 10;
int temp_sp = -1;
for (int i = 0; i < sp + 1; i++) {
temp[i] = stack[i];
}
temp_sp = sp;
clear();
for (int i = 0; i < temp_sp+1; i++) {
for (int j = i + 1; j < temp_sp+1; i++) {
if (!(temp[i] == temp[j])) {
push(temp[i]);
}
}
}
}
This is main function that I used to test out functions:
int main() {
push(1);
push(2);
push(3);
push(4);
push(3);
push(5);
removeDuplicates();
print();
return 0;
}
If there is simpler way to solve this by using C++ (not std::stack), let me know.
this code that is supposed to work for normal array, but not sure if it's right for stack as we might using dynamic memory
Whether your code is correct for stacks is nothing to do with dynamic allocation, and everything to do with the interface of a stack. Do you know what that is? It's absolutely essential to solving your problem, and I don't see any hint that you either know how a stack behaves, or tried to research it.
Here you are, the stack abstract datatype:
preserves last-in first-out order
allows you to push a new element onto the top of the stack
allows you to pop the most recently pushed element (that wasn't already popped) from the top of the stack.
That's everything, and there is no random access (ie, stack[j] will never be a valid expression), so it is obviously impossible for the algorithm you showed to work.
If you don't have a stack implementation already - write one! You're going to need a stack to compile and test your algorithm anyway. The definitions you show describe the storage, but not the interface.
There are only two functions to code (plus the two to create and destroy a stack, and optionally one to query the size).
Now for the algorithm - you can only ever access the top element of a stack, so you need to think about what to with the elements you pop that aren't duplicates. They have to go somewhere, because you can't see below them while they're on your main stack, and you mustn't lose them.
Your edit shows you do have a stack datatype, sort of: it uses three global variables which you have to take care not to break, and you can't reuse any of the functions for your temporary stack, because they operate on those globals.
Even in C, I'd expect to see something like this (untested, un-compiled sample code based on yours above)
struct Stack {
int size;
int sp;
int data[];
};
struct Stack* stack_create(int elements) {
struct Stack *s = malloc(sizeof(*s) + elements * sizeof(int));
s->size = elements;
s->sp = -1;
return s;
}
bool stack_isEmpty(struct Stack *s) { return s->sp == -1; }
bool stack_isFull(struct Stack *s) { return s->sp == s->size - 1; }
void stack_push(struct Stack *s, int x)
{
assert(!stack_isFull(s));
s->data[++s->sp] = x;
}
int stack_pop(struct Stack *s)
{
assert(!stack_isEmpty(s));
return s->data[(s->sp)--];
}
because then you can use the same operations on your main and temporary stacks.
If the removeDuplicates message is supposed to be implemented in terms of the stack abstraction, you need an algorithm you can implement in terms of stack_push, stack_pop etc.
If the removeDuplicates message is supposed to be an internal function operating directly on the stack implementation, rather than being implemented in terms of the stack abstraction - then your basic approach is probably OK (if very far from optimal), and you just need to learn to debug your code.
I still don't know which one of those is true (so I won't vote to re-open yet), but they are completely different questions.
I see a few problems with your current code:
In the loop
for (k = j; k < size; k++)
{
stack[k] = stack[k + 1];
}
you go out of bounds because you use stack[k+1]. How would you fix that?
But then after you have moved all the elements down by 1, the new stack[j] may be another duplicate of stack[i]. How would you fix that? You might consider using a while loop.
You use a global variable size which is the stack size. But there is also a variable sp that is the stack pointer and indicates the part of the stack in use. So instead of looping over size you should loop over sp.
Note what the stack pointer points at: the value -1 means stack empty, so any other value points at the current value at the top of the stack. (This is important beause the other interpretation of the stack pointer is that it points at the next free element of the stack.)
This sp of course decreases with every duplicate you remove from the stack.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Say I have a program that allocates a chunk of memory
char* get_date() {
char* date = malloc(100);
return date;
}
And I want to call the function a considerable number of times in the main function.
int main() {
int i;
for (i = 0; i < 10000; i++) {
char *c = get_date();
//do something
free(c);
}
return 1;
}
How can I reduce the number of times a new chunk of memory is allocated and just allocate one and overwrite it afterwards?
Somebody told me about something like this:
char *date = malloc(100);
for (i = 0; i < 10000; i++) {
char *c = get_date(date):
//do something
}
free(date);
But I am not sure how the new function, get_date should look like and why it should work.
Instead of having get_date return a pointer to the buffer with the data produced by the function, make it take a pointer to a buffer into which the data will be written. I.e. the prototype of get_date could be something like
void get_date(char *buf);
However, it might be useful for get_date() to be able to tell not only the starting address of the buffer but also the size of the buffer . That way,
the function can tell if the given buffer is too small (and then return e.g. an int indicating an error code). Hence, the prototype
int get_date(char *buf, size_t len);
might be more useful in practice.
On the caller side, you could then use e.g.
char date[100];
for (i = 0; i < 10000; i++) {
// return value 0 means success
if (get_date(date, sizeof date) == 0) {
//do something
}
}
I.e. in this case, you wouldn't need malloc or free at all.
You are trying to save 10,000 malloc / free calls?
Before you change your code, measure how long it takes. If you are too lazy to measure it, then the speed is not important, so don't change it.
100 bytes? Why are you using malloc() at all?
for (i = 0; i < 10000; i++) {
char c[100]:
//do something
}
If you have a function that returns temporary fixed size memory, the memory can be static:
thread_local char get_date_buffer [100];
char* get_date() {
// change get_date_buffer...
return get_date_buffer;
};
You must not free the return value and you must copy the data when reusing it and recalling the function. Many api-functions use this technique, like glGetString.
I have this problem in C where I have to implement a garbage collector. I'm stuck on the fact that I was given 4 functions to complete and not sure how they connect to one another. I'm not sure what to do. This is what I have so far:
void mygc() {
//int **max = (int **) 0xbfffffffUL; // the address of the top of the stack
unsigned long stack_bottom;
int **max = (int **) GC_init(); // get the address of the bottom of the stack
int* q;
int **p = &q; // the address of the bottom of the stack
while (p < max) {
//printf("0. p: %u, *p: %u max: %u\n",p,*p,max);
mark(*p);
p++;
}
//utilize sweep and coalesce (coalesce function already written)
}
void mark(int *p) {
int i;
int *ptr;
//code here
}
void sweep(int *ptr) {
// code here
}
int *isPtr(int *p) {
//return the pointer or NULL
int *ptr = start;
//code here
}
If you don't even understand the question perhaps it's best to speak to your teaching staff. To get you started here's the general idea.
mygc is obviously the top level function that does the GC.
mark is called to mark memory location/object as in use. It also needs to mark all memory referenced by that location/object as in use (recursive).
sweep is called to unmark all the previously marked memory and to claim back (garbage collect) those locations that are not marked.
isPtr is called to determine whether a memory location is a pointer (as opposed to being any other data). This is used by mark to know whether a memory location needs to be marked or not.
So putting that all together the general pseudo code is:
mygc()
{
loc_list = get stack extents and global variables
foreach (p in loc_list) {
if (isPtr(p)) {
mark(p)
}
}
foreach (p in heap) {
sweep(p)
}
}
There are obviously lots of details not dealt with in that psuedo code. But it should hopefully be enough to answer your original question which is how the four functions fit together.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
How to deallocate memory for the following code: I want to store names in name field of the given below structure struct tag and then deallocate the memory
SINT32 TestExample(void)
{
typedef struct tag
{
char *name;
} ST;
int i;
ST **p, **p1;
p = p1 = (ST **)calloc(1, 10 * sizeof(ST *));
for(i=0; i<10; i++)
{
p[0] = (ST *)calloc(1, 10 * sizeof(ST));
p[0]->name = (char *)malloc(20 * sizeof(char));
sprintf(p[0]->name, "Name_%d", i);
++p;
}
/* TO DO: free the memory allocated in previous block */
{
------------------------
}
p = NULL:
return 0;
}
Call free(object) on the same objects you called malloc on in a for loop
You should free name before freeing the struct.
p = p1;
for(i=0; i<10; i++)
{
free(p[i]->name);
free(p[i]);
}
free(p1);
The basic idea is that you should free the things you allocate memory to, in an order that allows you to free the other things.
You also need to "reset" the pointer p to the original address by doing p = p1;
as you can see here by doing
free(p);
be careful not to free memory that wasn't allocated, so you won't get debug assertion failed.