I am trying to create my own malloc function, and I did not finished yet. Here is related part of my code:
mymalloc.h :
#pragma once
#include <stdlib.h>
typedef struct METADATA{
struct METADATA *next;
struct METADATA *prev;
int free;
size_t size;
}METADATA;
METADATA *metadata;
void *mm_malloc(size_t size);
mymalloc.c
#include "mm_alloc.h"
#include "stdlib.h"
#include "stdio.h"
void *mm_malloc(size_t size) {
if(size == 0)
return NULL;
METADATA *tmp;
long address;
if(metadata == NULL){
sbrk(sizeof(tmp));
sbrk(size);
address = sbrk(0);
return (void *)address;
}
}
In the sbrk(sizeof(tmp)); part of mymalloc.c, I got "Implicit declaration of function sbrk()". What I wanted to do ise creating a place for metadata of new block and also a place for the required size. Where am I doing wrong?
Add the line
#include <unistd.h>
At the top of the file 'mymalloc.c' so that the function is declared
Related
I am new in C and literally trying to return pointer from my function to the pointer variable and have this "[Warning] assignment makes pointer from integer without a cast" no idea why compiler defines it as an int.
Can't declare my function before main as well, it throws this "undefined reference to `free_block'".
#include <stdio.h>
#include <stdlib.h>
struct block{
int num;
};
int main(int argc, char *argv[]) {
struct block *b;
b = free_block();
struct block *free_block(){
struct block *b = NULL;
return b;
}
return 0;
}
Thank you
Yea, my fault I know not too much about c syntax and had no idea about nested functions, soz.
But what could be wrong in this case:
I am trying to make my own memory allocator without using malloc or calloc functions. In my code I have the same Warning on the line with pointer = free_space_get(size);, here I have no more nested func(), my methods defined before main(), but still have no idea do I have to declare my functions or no, coz in the answer given to me it worked fine as soon as functions were defined before the main().
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct header{
size_t size;
struct header *next;
unsigned int free;
};
void *m_alloc(size_t size){
size_t total_size;
void *block;
struct header *pointer;
if(!size)
return NULL;
pointer = free_space_get(size);
if(pointer){
pointer->free = 0;
return (void*)(pointer + 1);
}
}
struct header *get_free_space(size_t size){
struct header *b = NULL;
return b;
}
int main() {
return 0;
}
Your code can be re-written as
#include <stdio.h>
#include <stdlib.h>
struct block{
int num;
};
struct block *free_block(){
struct block *b = NULL;
return b;
}
int main(int argc, char *argv[]) {
struct block *b;
b = free_block();
if(b == NULL) // Checking whether pointer is returned
printf("\n Recieved NULL \n");
return 0;
}
the implementation level of the array-based
#include "stack.h"
void creat_stack(Stack *s) {
s->Top = 0;
}
int isFull(Stack s) {
return (s.Top == Max ? 1 : 0);
}
int isEmpty(Stack s) {
return (s.Top == Max ? 1 : 0);
}
void push(stack_entry e, Stack *s) {
if (!isFull(*s))
s->entry[s->Top++] = e;
else
printf("Error : Stack Overflow\n");
}
void pop(stack_entry *e,Stack *s) {
if(!isEmpty(*s))
*e = s->entry[s->Top--];
else
printf("Error : Stack Underflow\n");
}
the header file stack.h that consists of the prototypes of the functions along with the definition of the stack element type stack_entry.
#pragma once
#include <stdio.h>
#define Max 10
typedef char stack_entry;
typedef struct Stack{
int Top;
stack_entry entry[Max];
}Stack;
void creat_stack(Stack *s);
int isFull(Stack s);
int isEmpty(Stack s);
void push(stack_entry e,Stack *s);
void pop(stack_entry *e, Stack *s);
so my question why i have to include the header file "stack.h" in the "stack.c" file ??
You should have to add the stack.h because this file is it who has all declarations of your typedef define struct and methods
So without then, will be impossible to access any of those informations.
It is the same if you declare a method below the main function and do not declare his signature upstairs the main, you cannot access..
So, all this happens with all include files that you use at the top of your file..
Do not forget C is a sequential language, so you will never know what do you have in the next line if you don't tell the compiler.
check more here
First, don't include "stdio.h" in the header file, you aren't use it there anyway. include it in the source file where you are using it.
You need to include the header file for the "struct stack" and the "define".
So I have these three files
Main.c
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include "support.h"
int main( void ) {
int* num1 = malloc(100);
printf("num1: %p", &num1);
}
Support.c
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "support.h"
void *malloc(size_t size) {
struct block_meta *block;
if (size <= 0) {
return NULL;
}
if (!global_base) { // First call.
block = request_space(NULL, size);
if (!block) {
return NULL;
}
global_base = block;
} else {
struct block_meta *last = global_base;
block = find_free_block(&last, size);
if (!block) { // Failed to find free block.
block = request_space(last, size);
if (!block) {
return NULL;
}
} else { // Found free block
block->free = 0;
block->magic = 0x77777777;
}
}
return(block+1);
}
void free(void *ptr) {
if (!ptr) {
return;
}
struct block_meta* block_ptr = get_block_ptr(ptr);
assert(block_ptr->free == 0);
assert(block_ptr->magic == 0x77777777 || block_ptr->magic == 0x12345678);
block_ptr->free = 1;
block_ptr->magic = 0x55555555;
}
void *realloc(void *ptr, size_t size) {
if (!ptr) {
// NULL ptr. realloc should act like malloc.
return malloc(size);
}
struct block_meta* block_ptr = get_block_ptr(ptr);
if (block_ptr->size >= size) {
// We have enough space. Could free some once we implement split.
return ptr;
}
// Need to really realloc. Malloc new space and free old space.
// Then copy old data to new space.
void *new_ptr;
new_ptr = malloc(size);
if (!new_ptr) {
return NULL; // TODO: set errno on failure.
}
memcpy(new_ptr, ptr, block_ptr->size);
free(ptr);
return new_ptr;
}
void *calloc(size_t nelem, size_t elsize) {
size_t size = nelem * elsize; // TODO: check for overflow.
void *ptr = malloc(size);
memset(ptr, 0, size);
return ptr;
}
Support.h
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
void *malloc(size_t size);
void free(void *ptr);
void *realloc(void *ptr, size_t size);
struct block_meta {
size_t size;
struct block_meta *next;
int free;
int magic; // For debugging only. TODO: remove this in non-debug mode.
};
#define META_SIZE sizeof(struct block_meta)
void *global_base = NULL;
struct block_meta *find_free_block(struct block_meta **last, size_t size) {
struct block_meta *current = global_base;
while (current && !(current->free && current->size >= size)) {
*last = current;
current = current->next;
}
return current;
}
struct block_meta *request_space(struct block_meta* last, size_t size) {
struct block_meta *block;
block = sbrk(0);
void *request = sbrk(size + META_SIZE);
assert((void*)block == request); // Not thread safe.
if (request == (void*) -1) {
return NULL; // sbrk failed.
}
if (last) { // NULL on first request.
last->next = block;
}
block->size = size;
block->next = NULL;
block->free = 0;
block->magic = 0x12345678;
return block;
}
struct block_meta *get_block_ptr(void *ptr) {
return (struct block_meta*)ptr - 1;
}
However when I attempt to compile using
gcc -o asgn2 main.c support.c
I get the error
/tmp/ccscmcbS.o:(.bss+0x0): multiple definition of `global_base'
/tmp/ccyjhjQC.o:(.bss+0x0): first defined here
/tmp/ccscmcbS.o: In function `find_free_block':
support.c:(.text+0x0): multiple definition of `find_free_block'
/tmp/ccyjhjQC.o:main.c:(.text+0x0): first defined here
/tmp/ccscmcbS.o: In function `request_space':
support.c:(.text+0x55): multiple definition of `request_space'
/tmp/ccyjhjQC.o:main.c:(.text+0x55): first defined here
/tmp/ccscmcbS.o: In function `get_block_ptr':
support.c:(.text+0xfe): multiple definition of `get_block_ptr'
/tmp/ccyjhjQC.o:main.c:(.text+0xfe): first defined here
collect2: error: ld returned 1 exit status
I dont believe that I declared those methods more than once, also it is in a much different format than I am usually given. Not quite sure what it means.
The problem is that you have functions and globals defined (as opposed to declared) in your header file. Therefore, those functions are pulled into both main.c and support.c when they are compiled. Then during the linking phase, the linker sees multiple definitions.
Even if you had include guards, it wouldn't help in this case because that only defends against multiple definitions in a single compilation unit, not across multiple units.
Take the definitions of those function out of the header file, replace them with declarations, and put them either in support.c or in a separate .c file.
You can use the -fcommon option for gcc.
Make sure that the header is included only once, so add something like the following to the headers source code:
#ifndef _HAVE_SUPPORT_H
#define _HAVE_SUPPORT_H
// ...
// YOUR HEADER SOURCE CODE
// ...
#endif //_HAVE_SUPPORT_H
As I said this makes sure that the header is included only once, because then it defines _HAVE_SUPPORT_H. If now another source tries to include it, it will not do anything because _HAVE_SUPPRORT_H is already defined.
It also helps if you have only function declarations in the header and your 'real' functions will be in another *.c file.
Edit:
The second parts is the most important for your problem as #kaylum noticed
For me the solution was simple, downgrade to previous GCC version.
Here is comparison gcc installed on two different Ubuntu version.
GCC for ubuntu 20.04: https://packages.ubuntu.com/focal/gcc (gcc 9)
GCC for ubuntu 22.04: https://packages.ubuntu.com/jammy/gcc (gcc 11)
Because on my case, code was legacy code from about 20 years ago, then it makes sense for me to keep using old compiler.
I am trying to declare a struct and use it in multiple files and I am getting an error that I cannot figure out. Sample code is posted below.
in test.h
#ifndef TEST_H
#define TEST_H
struct mystruct;
struct mystruct *new_mystruct();
void myprint(struct mystruct*,int);
#endif
int test.c
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
struct mystruct {
int *myarray;
};
struct mystruct *new_mystruct(int length)
{
int i;
struct mystruct *s;
s = malloc(sizeof(struct mystruct));
s->myarray = malloc(length*sizeof(int));
for(i = 0; i < length; ++i)
s->myarray = 2*i;
return s;
}
in main.c
#include "test.h"
#include <stdio.h>
int main()
{
int len = 10;
struct mystruct *c = new_mystruct(len);
myprint(c, len);
printf("%f", c->myarray[3]); // error: dereferencing pointer to incomplete type
return 0;
myprint() prints out 0 2 4 6 8 10 12 14 16 18. why doesn't the myprint(function work but the printf statement doesn't? why is it ok to pass it into a function but not use it in main? Thanks.
Currently main() only knows that struct mystruct is a type, but it doesn't know anything about its internal structure, because you've hidden it in test.c.
So you need to move this definition:
struct mystruct {
int *myarray;
};
from test.c to test.h, so that it's visible to main().
Note: what you're doing here is a classic example of an opaque type. This can be a very useful technique when you want to hide implementation details from code that is going to be calling your API.
Main.c doesn't know the contents of the mystruct structure. Try moving these lines:
struct mystruct {
int *myarray;
};
from test.c to test.h.
While you're at it, I think you mean "int myarray" not "int *myarray".
gcc 4.4.4 c89
I am keep getting a "Cannot dereference to incomplete type".
However, I am sure I have my structure type complete. I return the Network_t instance that is the pointer to the allocated memory. I should be able to dereference that memory.
Many thanks for any advice,
I have this in my header file:
driver.h
typedef struct Network_t Network_t;
Network_t* create_network(int id);
Implementation file
driver.c
#include "driver.h"
struct Network_t {
int id;
};
Network_t* create_network(int id)
{
Network_t *network = malloc(sizeof *network);
if(network) {
network->id = id;
}
return network;
}
And in my main.c
#include "driver.h"
Network_t *network = NULL;
network = create_network(1);
printf("Network ID: [ %d ]\n", network->id); /* Cannot dereference pointer to incomplete type */
From main.c you only have a forward declaration of struct Network_t visible. To access id from a pointer to struct Network_t you need a definition of the struct to be visible at the point at which you dereference it.
You could move the definition from driver.c to driver.h.
this one works
in driver.h
#include <stdio.h>
#include<stdlib.h>
struct Network_t{
int id;
};
Network_t *create_network( int id){
Network_t *network=(Network_t *)malloc(sizeof(network));
if (network){
network->id=id;
}
return network;
}
in Network.cpp
#include <iostream>
#include "driver.h"
using namespace std;
int main(){
Network_t *network=NULL;
network=create_network(1);
printf("Network ID:[%d]\n",network->id);
return 0;
}
result:
Network ID:[1]