Weird Error when implementing Stack in C - c

I'm trying to implement stack in C and it got the weird error in my MinGw compiler
gcc -Wall -o stack stack.c
Stack.c
#include "stack.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
Stack *create(int size) {
Stack *result;
result = (Stack *) malloc( sizeof(Stack) * size );
assert(result != NULL);
result -> file = result;
result -> maxAllocate = size;
result -> top = -1;
return result;
}
stack.h
#define MAX_SIZE 1024
typedef struct {
void **file;
int top;
int maxAllocate; // current size of array allocated for stack
} Stack;
Stack *create(int size);
int push(Stack *s, void *x);
void *pop(Stack *s);
int isEmpty(Stack *s);
error
C:\test>gcc -Wall -o stack stack.c
stack.c: In function 'create':
stack.c:26:17: warning: assignment from incompatible pointer type [enabled by de
fault]
c:/mingw/bin/../lib/gcc/mingw32/4.6.2/../../../libmingw32.a(main.o): In function
`main':
C:\MinGW\msys\1.0\src\mingwrt/../mingw/main.c:73: undefined reference to `WinMai
n#16'
collect2: ld returned 1 exit status

With gcc -Wall -o stack stack.c you compile only stack.c (which has o main function in it) but for a functioning application you will also need a main function, as the main entry point: http://en.wikipedia.org/wiki/Entry_point

using gcc with -o option means you want to compile, link and run your program (this command won't run it, but usually that's the reason with such usage). You cannot run a program without an entry point (in this case it's main function).
If you only want to check if your stack.c compiles use gcc -Wall -c stack.c.

Related

How to resolve linker when when using multiple files in Virtual-C? [duplicate]

I have this simple test file:
#include "stack.h"
int main()
{
Stack* stck = init_stack();
return 0;
}
and stack.h is defined as follows:
#ifndef STACK_H
#define STACK_H
#define EMPTY_STACK -1
typedef struct stack
{
char ch;
struct stack* prev;
} Stack;
extern Stack* init_stack();
extern char pop(Stack*);
extern void push(Stack*, char);
#endif
These two files are in the same directory. But when I do gcc .. to build it, I keep getting the error below:
$ ls
stack.c stack.h teststack.c
$ gcc -o testit teststack.c
/tmp/ccdUD3B7.o: In function `main':
teststack.c:(.text+0xe): undefined reference to `init_stack'
collect2: ld returned 1 exit status
Could anyone tell me what I did wrong here?
Thanks,
gcc -o testit teststack.c stack.c
You need to compile both C source files and link the object files; this does it all in one command.

undefined reference to `stack_init'

test.c
#include <stdio.h>
#include <stdlib.h>
#include "dslib.h"
//#include "stack.c"
int main()
{
stack myStack;
char buffer[1024];
stack_init(&myStack, 6);
int i;
for(i = 0; i < myStack.max; i++){
stack_push(&myStack, (i+1)*2);
}
printf("Hello\n");
return 0;
stack.c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "dslib.h"
//#define stack_init main
void stack_init(stack *s, int capacity)
{
// struct stack_t *s = (struct stack_t*)malloc(sizeof(struct stack_t));
s->max = capacity;
s->count = -1;
s->data = (int*)malloc(capacity * sizeof(int));
//return s;
}
int stack_size(stack *s)
{
return s->count;
}
int stack_pop(stack *s)
{
if(s->count == 0){
return -1;
}
s->count--;
int pop = s->data[s->count];
s->data[s->count] = 0;
return pop;
}
void stack_push(stack *s, int e)
{
if(s->count != s->max){
s->data[s->count] = e;
s->count++;
}
}
void stack_deallocate(stack *s)
{
free(s->data);
}
dslib.h
#ifndef DSLIB_H
#define DSLIB_H
#include <stdio.h>
#include <stdlib.h>
typedef struct stack
{
int count; // the number of integer values currently stored in the stack
int *data; // this pointer will be initialized inside stack_init(). Also, the actual size of
//the allocated memory will be determined by “capacity’ value that is given as one of the
//parameters to stack_init()
int max; // the total number of integer values that can be stored in this stack
}stack;
void stack_init(stack* s, int capacity);
int stack_size(stack *s);
int stack_pop(stack *s);
void stack_push(stack *s, int e);
void stack_deallocate(stack *s);
#endif
Makefile
cc=gcc
file: test.o stack.o file.o
gcc -o file test.o stack.o file.o
file.o: file.c
gcc -o file.o file.c
test.o: test.c
gcc -o test.o test.c
stack.o: stack.c
gcc -o stack.o stack.c
When I execute make, it emits this:
gcc -o test.o test.c
/tmp/ccJMitGw.o: In function `main':
test.c:(.text+0x2a): undefined reference to `stack_init'
test.c:(.text+0x53): undefined reference to `stack_push'
collect2: error: ld returned 1 exit status
Makefile:10: recipe for target 'test.o' failed
make: *** [test.o] Error 1
gcc -o test.o test.c
This attempts to compile and link test.c into an executable with the unusual name of test.o. That obviously fails because test.c is not a complete program by itself.
To just compile and assemble a source file into an object file, you need to use the -c option:
gcc -c -o test.o test.c
And the same for the other compilation rules of your makefile.
There is a slight inconsistency in gcc's behavior here: it looks at the extension of the input files to help it decide what to do (.c files get compiled as C, .cpp files are compiled as C++, .s files are only assembled, etc) but it doesn't look at the extension of the output file. You have to use a separate option.
My answer is intended to follow on Nate's. Mine's a bit too complicated to put into a comment.
The default file production rules should work just fine for your Makefile unless on your platform the defaults are different. On mine, this is all I need to make the executable:
file: test.o stack.o
gcc -o file test.o stack.o
You didn't include file.c but the code you posted doesn't depend upon file.c.
It's highly recommended to use pre-defined rules whenever possible and to define new rules where they can be applied more than once. The only time you truly need specific rules is when multiple rules cannot be refactored to a smaller set of rules.
PS I'd never want to create an executable named for something that already exists.
Create a header file for the stack.c file and include it in your main file instead of stack.c
stack.h
#ifndef STACK_H
#define STACK_H
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "dslib.h"
void stack_init (stack * s, int capacity);
int stack_size (stack * s);
int stack_pop (stack * s);
void stack_push (stack * s, int e);
void stack_deallocate (stack * s);
#endif
stack.c
#include "stack.h"
/* code */
test.c
#include "stack.h"
/* code */

The address of a pointer returned by some function gets changed, why? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Sorry I cannot post any reproducible code as it's part of the code of a large project.
The snippet is
struct res_data *getRes(int id) {
struct res_data *ret = malloc(sizeof(*ret));
/*
* res.aa = getAA(), etc...
*/
// print ret got: 0x55ffb23ce000
fprintf(stderr, "return: ret: %p\n", ret);
return ret;
}
Then
struct res_data *data = getRes(id);
fprintf(stderr, "got: %p\n", data);
// print data got: 0xffffffffb23ce000
Why is that? Any possible cause?
Transferring comments in answer.
Diagnosis
I'd lay odds you've not properly declared getRes() in a header that is used both where it is defined and where it is used, so the place where it is used thinks that it got a 32-bit int from getRes(), which it then sign-extended to create the pointer saved in data.
The last 8 hex digits (B23CE000) are the same in both values, but the original pointer in getRes() had some zero-bits in the leading 4 bytes, but that in the calling code has all bits 1, indicating sign-extension.
Moral: make sure you have accurate prototypes in force. Make your compiler insist on them. Heed its warnings!
Here is some code that reproduces the problem — but it is hair-raising to me. I don't normally publish code like this.
main31.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
// Incorrect declaration, but what the compiler infers, more or less
// extern int getRes(int id);
int main(void)
{
struct res_data *data = (struct res_data *)getRes(31);
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)data);
//free(data); // free fails because the pointer is incorrect
return 0;
}
getres31.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
struct res_data
{
int id;
char part2[32];
double part3;
};
extern struct res_data *getRes(int id);
struct res_data *getRes(int id)
{
struct res_data *ret = malloc(sizeof(*ret));
ret->id = id;
ret->part2[0] = '\0';
ret->part3 = 0.0;
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)ret);
return ret;
}
This code is essentially clean, except that the declaration of getRes() should be in a header included in both getres31.c and main31.c.
Compilation and running
Normally, I compile with -Werror set so the warnings would cause the compilation to fail.
$ make so-6051-9209-a
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o main31.o main31.c
main31.c: In function ‘main’:
main31.c:10:48: warning: implicit declaration of function ‘getRes’; did you mean ‘gets’? [-Wimplicit-function-declaration]
10 | struct res_data *data = (struct res_data *)getRes(31);
| ^~~~~~
| gets
main31.c:10:29: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
10 | struct res_data *data = (struct res_data *)getRes(31);
| ^
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o getres31.o getres31.c
gcc -o so-6051-9219-a -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes main31.o getres31.o
$
When run, the output varies:
$ ./so-6051-9219-a
getRes: 0x00007FDF41D02620
main: 0x0000000041D02620
$ ./so-6051-9219-a
getRes: 0x00007F868AC02AA0
main: 0xFFFFFFFF8AC02AA0
$
Sometimes, the value received in main() is interpreted as positive, sometimes as negative, but the value is sign-extended.
Prescription
The fix is to put the declaration of getRes() into a header, and include that header in both source files.
main37.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "getres37.h"
int main(void)
{
struct res_data *data = getRes(31);
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)data);
free(data);
return 0;
}
Note that it is safe to free the data this time.
getres37.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "getres37.h"
struct res_data
{
int id;
char part2[32];
double part3;
};
struct res_data *getRes(int id)
{
struct res_data *ret = malloc(sizeof(*ret));
ret->id = id;
ret->part2[0] = '\0';
ret->part3 = 0.0;
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)ret);
return ret;
}
getres37.h
#ifndef GETRES37_H_INCLUDED
#define GETRES37_H_INCLUDED
extern struct res_data *getRes(int id);
#endif /* GETRES37_H_INCLUDED */
Compilation and running
$ make so-6051-9219-b
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o main37.o main37.c
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o getres37.o getres37.c
gcc -o so-6051-9219-b -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes main37.o getres37.o
$
No warnings!
$ ./so-6051-9219-b
getRes: 0x00007FBA11600700
main: 0x00007FBA11600700
$ ./so-6051-9219-b
getRes: 0x00007FED23C02AA0
main: 0x00007FED23C02AA0
$
This time, there's no problem; the value of the pointer in main() matches the value in getRes().
Note that the header declares an opaque (incomplete) type struct res_data and declares a function that returns a pointer to that type. The main() function cannot dereference the pointer it is returned — it doesn't know (or need to know) the details of the structure. That's hidden in the file containing getRes(). This is the way that C supports information hiding. Using an opaque structure type is much safer than the alternative sometimes seen, which is using void * everywhere. That is dangerous as it provides no type safety, unlike the opaque structure types.
Also note that it was easy to create an MCVE (Minimal, Complete, Verifiable Example)
(or MRE or whatever name SO now uses)
or an
SSCCE (Short, Self-Contained, Correct Example). It really didn't require very much code at all. But it does make life so much easier — we don't have to do the guesswork!
JFTR: Testing on a MacBook Pro running macOS Mojave 10.14.6, using GCC 9.2.0 plus Xcode 11.3.1.
The most likely cause for this surprising behavior is a missing prototype for getRes() when you call this function from main().
Declare the function in a header that you include in both files as
extern struct res_data *getRes(int id);

Linker error when using a function defined in a custom shared library

I created following shared library and wanted to use the functions defined in the library in a different c file.
Header file :
#ifndef _MY_MALLOC_H_
#define _MY_MALLOC_H_
#include <dlfcn.h>
#include <stdio.h>
extern void* malloc(size_t sz);
extern void free(void *p);
extern int get_total_malloc_requested(void);
#endif
Implementation:
#define _GNU_SOURCE
#include "my_malloc.h"
static int num_times_malloc_called = 0;
static int num_times_free_called = 0;
void* malloc(size_t sz)
{
void *(*libc_malloc)(size_t) = dlsym(RTLD_NEXT, "malloc");
num_times_malloc_called++;
fprintf(stderr,"malloc called %d\n",num_times_malloc_called);
return libc_malloc(sz);
// return NULL;
}
void free(void *p)
{
void (*libc_free)(void*) = dlsym(RTLD_NEXT, "free");
fprintf(stderr,"free\n");
libc_free(p);
}
int get_total_malloc_requested(void){
return num_times_malloc_called;
}
There was no problem when I created the .so.
gcc -shared -fPIC -o my_malloc.so my_malloc.c -ldl
But when I am invoking get_total_malloc_requested from another .c file, I get linker error.
#include <stdio.h>
#include <stdlib.h>
#include "my_malloc.h"
int main(){
void *ptr;
ptr = malloc(64); <---no problem here
fprintf(stderr,"called malloc ");
free(ptr);<---no problem here
ptr = malloc(64);
fprintf(stderr,"called malloc ");
free(ptr);
get_total_malloc_requested();<---linker doesn't find the symbol
return 0;
}
gcc hello.c -o hello.o -L ./my_malloc.c
ld: warning: -L path './my_malloc.c' is not a directory
Undefined symbols for architecture x86_64:
"_get_total_malloc_requested", referenced from:
_main in hello-1dfbf1.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You created a shared object, but you are not creating an executable to use it. Since the executable is not using it, the referenced symbol is not found.
Remove the extraneous -L option, and specify the shared object when linking.
gcc hello.c -o hello ./my_malloc.so

GCC Error but VS no error

When I compile the below program it is giving me this error.
/tmp/ccwr6gsJ.o: In function 'main':
main.cL(.text+0xa): undefined reference to 'example'
collect2: error: Id returned 1 exit status
Main.c:
#include <stdio.h>
#include "includes.h"
int main()
{
int exampleInt = example();
return 0;
}
includes.h:
int example();
includes.c:
#include "includes.h"
int example()
{
int i = 3;
return i;
}
It seems to work in Visual Studio but not on GCC on Linux
This is very likely a build error, i.e. you're calling the compiler on the wrong set(s) of files, and/or not doing a linking step.
Try:
$ gcc -o myprog main.c example.c
Note that a mere #include in a C file does not in any way tell the compiler to compile more C files.

Resources