I want to implement a stack using structures in C. Unfortunately, printf throws a segmentation fault. Perhaps there is a problem with dynamic allocation. Does anyone know how to solve it?
I have been facing this issue for the last two days. Your help will be very helpful for my study.
Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 256
typedef int (*pf)();
typedef struct _stack{
int arr[SIZE];
int top;
pf push, pop, peek, isEmpty, size, clear, print;
} stack;
void *nstack(){
stack *pstack = (stack *)malloc(sizeof(stack));
void push(int data) {
if(pstack->top < SIZE-1) pstack->arr[++pstack->top]=data;
}
int pop() {
return (pstack->top >= 0)?pstack->arr[pstack->top--]:0;
}
int peek(){
return (pstack->top >= 0)?pstack->arr[pstack->top]:0;
}
bool isEmpty(){
return (pstack->top >= 0)?false:true;
}
int size(){
return pstack->top+1;
}
void clear(){
pstack->top = -1;
}
void print(){
if(!isEmpty()){
for(int i = 0; i <= pstack->top; i++) printf("%d", pstack->arr[i]);
printf("\n");
}
}
pstack->push=push;
pstack->pop=pop;
pstack->peek=peek;
pstack->isEmpty=isEmpty;
pstack->size=size;
pstack->clear=clear;
pstack->print=print;
pstack->top=-1;
return pstack;
}
void dstack(stack *pstack){
free(pstack);
}
void main() {
stack *A = nstack();
A->push(1);
A->push(4);
A->push(6);
printf("%d",A->pop());
printf("%d",A->pop());
dstack(A);
}
While the code compiles (with warning), it try to leverage GCC extensions for functions within functions. However, the internal functions must be called within a valid context - they try to access the local pstackof the nstack function - but it does not exists.
While this style work in many OO langauges (Java, and possibly C++), that support 'closures' or lambda, it does not work for C. Consider changing the interface for each of the function to take stack *, and change the calling sequence to pass it.
void push(stack *pstack, int data) {
if(pstack->top < SIZE-1) pstack->arr[++pstack->top]=data;
}
main() {
...
A->push(A, 1) ;
...
printf("%d", A->pop(A) ;
}
Really, you should edit your question and provide the exact errors but I've decided to do some of the legwork for you since you're probably pretty new to this.
So first thing I did was compile your code here with -Wall and look what I get:
SO_stack.c: In function ‘nstack’:
SO_stack.c:49:17: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->push=push;
^
SO_stack.c:52:20: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->isEmpty=isEmpty;
^
SO_stack.c:54:18: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->clear=clear;
^
SO_stack.c:55:18: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
pstack->print=print;
^
SO_stack.c: At top level:
SO_stack.c:66:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
void main() {
Let's look at the first error on line 49: pstack->push=push;
You've defined push function prototype as: void push(int data) but pstack->push is of type pf which is defined as int (*pf)(); See the problem here? You're trying to pass an argument to a function pointer that is not properly defined to handle the argument AND the return type is different. This is totally wrong. Your push(int data) implementation declares a return type of void and a parameter of int yet your pointer to this function declares a return type of int and a parameter of void. This is the case with push, isEmpty, clear, and print. You're going to have to decide if all of these functions need to have the same prototype or if you need to create several different function pointer types to handle them, etc...
So that's the first problem.
Second problem is that as the warning says, you have a void main() prototype for your main function. You should return int from main and specify a return code to the caller of main (likely the OS)... Commonly, successful execution returns 0 and failure returns -1 but this is specific to the platform so you can instead return EXIT_SUCCESS on success and return EXIT_FAILURE upon failure from main. For this macros to be defined, you need to have #include <stdlib.h> present, which you do.
Next issue is that as a commenter wrote, you should learn to use a debugger such as GDB, LLDB, or Windows Debugger so that you can figure out exactly where the program crashes.
I've not re-written your program because it has so many issues that I don't think it would be constructive to do so in this iteration, however, provide an exact error next time, and use the debugger to see if the crash happens inside of the actual printf() code as you implied, or it happens because you supplied corrupt memory to the printf function. My guess is that it is the latter... Meaning, it is in fact probably your code which is flawed and supplying an invalid char * to printf which is either out of bounds, nonexistent, etc... This is precisely what you will use a debugger to find out, by placing a breakpoint before the trouble code and watching the memory to see what's going on.
You need to either remove int data.
Work on this some more, and you will probably find the rest of the issues yourself, if there are any. You should compile with flag -Wall and consider compiling with flag -Werror to clear this kind of stuff up yourself in the future.
Related
I'm trying to get rid of warning: assignment from incompatible pointer type [-Wincompatible-pointer-types] while adding func2 in this simplified example of dealing with a huge open source C library - which has a lot of functions like func1 and defines like str1.func = func1;. Is it possible to fix this warning without modifying func1 or writing something specific for each function / its' defines?
This code at OnlineGDB - https://onlinegdb.com/ry5rNlvDG , click "Fork this" to modify
#include <stdio.h>
void func1(int a) { // please don't change
printf("%i\n", a);
}
void func2(int a, char c) {
printf("%i - %c\n", a, c);
}
struct bigstruct {
// void (*func) (int a); // old way
void (*func) (int a, char c); // ??? - some magic needed
};
int main()
{
struct bigstruct str1, str2;
str1.func = func1; // please don't change
// ^^^ gives a warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
str2.func = func2;
error; // onlinegdb - error on purpose to see the warnings
}
UPDATE: eventually I figured out this is indeed impossible, but I got away from this situation just by adding a new field to the structure that has been passed around through this open source library from one function to another, and as result didn't have to add a new argument to the function. I'm giving top answer to "#Rarity" for his best attempt
I don't quite get your concern, if it's warning you're after, then -Wno-incompatible-pointer-types is probably ok.
Else, if you want to suppress warnings selectively, then change func declaration to:
struct bigstruct {
void (*func) ();
};
, then func will accept various function pointers. Type void ()() in C is "function which takes unknown number of unknown arguments (and returns nothing)", unlike void()(void) which is "a function that takes no arguments".
With your "please don't change"s it is not possible. However, you could make a cast:
str1.func = (void(*)(int, char))func1;
The function will be called with 2 parameters but it takes only one. On Intel and VC the second parameter will be ignored. (Parameters are pushed right-to-left onto the stack and func1 will only access the first parameter and will be unaware of any other parameters higher on the stack). This could be different on other architectures.
The code given below is an exercise that our teacher gave to prepare us for exams.
We are supposed to find the errors that occur in this code and fully explain them .
#define SIZE 10
int start (void a,int k) {
const int size=10;
char array[size];
char string[SIZE];
mycheck(3,4);
array[0]=string[0]='A';
printf("%c %c\n", array[0], string[0]);
myRec(7);
}
int mycheck(int a , int b) {
if (a==0 || b==0 ) {
return 0;
}
else {
return (a*b);
}
}
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d,",x);
myRec(x--);
}
I have found these errors so far:
1.int start (void a,int k)
explanation: We can't have a variable of type void, because void is an incomplete type
2.const int size=10;
explanation:we can't use variable to define size of array
(problem is when I run it in dev-c++ it doesn't show an error so I'm not sure about this)
3.mycheck(3,4);
explanation: prototype of function mycheck() is not declared, so the function mycheck is not visible to the compiler while going through start() function
4.A friend told me that there is an error in function myRec because of this statement myRec(x--);
(I don't really get why is this an error and how you can I explain it?)
5.Main() function doesn't exist.
I'm not sure about this but if i run the code (in dev-c++) without main function I get a compilation error
I'm not sure if the errors that I pointed out are 100% right or if I missed an error or if I explained them correctly.
Please correct me if any of the above is wrong!
a friend told me that there is an error in function myRec cuz of this
statement myRec(x--);
It will lead to stackoverflow. Due to post-decrement, the actual argument passed to function myRec(), never decreases and therefore the condition:
if(x==0)
return 0;
will never become true. Regarding your rest of the errors, it depends on the compiler version being used:
For example C99, you are allowed to have variable size arrays like this:
const int size=10;
char array[size];
char string[SIZE];
but pre C99, you would have to use malloc or calloc. For your functions used without prototype, most compilers would generate a warning and not error and also due to no #include<stdio.h> statement, your printf would also lead to a warning.i Again, lot of these things are compiler dependent.
1.int start (void a,int k)
explanation: We can't have a variable of type void ,because void is an
incomplete type
Correct.
2.const int size=10;
explanation:we can't use variable to define size of array (problem is
when i run it in dev-c++ it doesnt show an error?so im not sure about
this!)
This is also correct, that char array[size];, where size is not a compile-time constant, is invalid in C89. However, in C99 and newer, this is actually valid and would create a variable-length array. It is possible that your Dev-C++ IDE is using GCC with the language set to C99 or newer, or has GNU C extensions enabled to enable this feature.
3.mycheck(3,4);
explanation: prototype of function mycheck() is not declared.So the
function mycheck is not visible to the compiler while going through
start() function
Correct. This can be fixed either by declaring the function's prototype before the start() function, or just moving the whole function to the top of the file. As noted by Toby Speight in the comments, in C89, this should not actually be a compiler error, since functions are implicitly declared when they are used before any actual declaration as int (), i.e. a function returning int with any arguments, which is compatible with the declarations of mycheck and myRec. It is however bad practice to rely on this, and implicit function declaration does not work in C99 or newer.
4.a friend told me that there is an error in function myRec cuz of this statement myRec(x--);
(I don't really get why is this an error and how you can explain it?)
This function is a recursive function. This means it calls itself within itself in order to achieve a kind of looping. However, this function as it is currently written would run forever and cause an infinite loop, and since it is a recursive function, and needs a new stack frame each time it is called, it will most likely end in a stack overflow.
The function is written with this statement:
if(x==0)
return 0;
This is intended to terminate the recursion as soon as x reaches 0. However, this never happens, because of this line of code here:
myRec(x--);
In C, postfix -- and ++ operators evaluate to their original value before the addition or subtraction:
int x = 5;
int y = x--;
/* x is now 4; y is now 5 */
However, using the prefix version of these operators will evaluate to their new value after adding / subtracting 1:
int x = 5;
int y = --x;
/* x is now 4; y is now 4 */
This means that on each recursion, the value of x never actually changes and so never reaches 0.
So this line of code should actually read:
myRec(--x);
Or even just this:
myRec(x - 1);
5.Main() function doesn't exist ...again im not sure about this but if i run the code (in dev-c++) without main function i get a compilation
error
This one could either be right or wrong. If the program is meant to run on its own, then yes, there should be a main function. It's possible that the function start here should actually be int main(void) or int main(int argc, char *argv[]). It is entirely valid however to compile a C file without a main, for example when making a library or one individual compilation unit in a bigger program where main is defined in another file.
Another problem with the program is that myRec is used before it is declared, just like your point 3 where mycheck is used before it is declared.
One more problem is that the functions start and mycheck are declared to return int, yet they both do not contain a return statement which returns an int value.
Other than that, assuming that this is the entire verbatim source of the program, the header stdio.h isn't included, yet the function printf is being used. Finally, there's the issue of inconsistent indentation. This may or may not be something you are being tested for, but it is good practice to indent function bodies, and indentation should be the same number of spaces / tab characters wherever it's used, e.g.:
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d,",x);
myRec(x--);
}
1) Hello friend your Recursive function myRec() will go infinite because it
call itself with post detriment value as per C99 standard it will
first call it self then decrements but when it call itself again it have
to do the same task to calling self so it will never decrements and new
stack is created and none of any stack will clear that recursion so
stack will full and you will get segmentation fault because it will go
beyond stack size.
2) printf("%d,",x); it should be printf("%d",x); and you should include #include library.
I think your another mistake is you are calling your mycheck() and you
returning multiplication of two integer but you are not catch with any
value so that process got west.So while you are returning something you
must have to catch it otherwise no need to return it.
3) In this you Program main() function missing. Program execution starts
with main() so without it your code is nothing. if you want to execute
your code by your own function then you have to do some process but
here main() should be present.or instead of start() main() should
be present.
4) you can also allocate any char buffer like this int j; char array[j=20];
your code should be like this.
#include<stdio.h>
#define SIZE 10
int mycheck(int a , int b) {
if (a==0 || b==0 ) {
return 0;
}
else {
return (a*b);
}
}
int myRec(int x) {
if(x==0)
return 0;
else
printf("%d",x);
myRec(--x);
}
void main (int argc, char** argv) {
const int size=10;
char array[size];
char string[SIZE];
int catch = mycheck(3,4);
printf("return value:: %d\n",catch);
array[0]=string[0]='A';
printf("%c %c\n", array[0], string[0]);
myRec(7);
printf("\n");
}
Enjoy.............
I'm having trouble returning a void pointer to another function in C.
HEADER FILE:
void *function2( void );
MAIN.C
#include "myHeader.h"
void function1 (){
void *temp = NULL;
temp = function2();
}
FUNCTION2.C
int a = 3;
void *function2(void){
printf("Memory Address %p\n",&a );
return (void *) &a; // value of &a is 0x100023444
}
However, the value of temp in function1() is 0x3444,instead of 0x100023444.
Does anyone know a solution for this, or if I am doing something wrong?
EDITED:
It seems, the header was added in the wrong place, leading to the problem described by AndreyT and Jonathan below, which seems to have fixed the truncation problem. Thanks for your help guys!
Given the revision to the question, I'm confident the problem is that you did not declare function2() before you used it. Consequently, the compiler thinks it returns an int, not a void *. It should also be complaining about the actual definition not matching the assumed declaration.
You should make sure your compiler options require you to define or declare a full prototype for each function before you use it.
Note that you should declare void *function2(void); because omitting the void in the parameter list means something quite different — it means the compiler is not told anything about what parameters it takes, not that it takes no parameters. (This is a difference from C++.)
You still have problems because you're returning a pointer to a local variable. You can probably print the pointer (though even that is not guaranteed by the standard), but you cannot reliably use it.
extern void *function2(void);
void function1(void)
{
void *temp = function2();
printf("Address: %p\n", temp);
}
void *function2(void)
{
int a = 3;
printf("Address: %p\n", &a);
return &a; // value of &a is 0x1200001234
}
Or define function2() before defining function1().
Note that it is crucial to include the header both where the function is defined (to make sure the definition is consistent with the header) and where the function is used (to make sure the use is consistent with the header). As long as you do this, all will be well.
Inside function1 you are calling a yet-undeclared function function2. In classic C language (C89/90) this is allowed, but an undeclared function is assumed to return an int. Apparently, on your platform pointers are 64 bits wide and int is 32 bits wide. This is what causes a truncation of your 64-bit pointer value 0x1200001234 to 32 bits, giving you 0x1234.
Formally, your code has undefined behavior, since after causing the compiler to assume that function2 returns int you declared it as returning void *. Even C89/90 compilers usually issue a warning about this problem (and C99 compiler report an error). Did you ignore it?
Either move the entire definition of function2 up and place it above function1
void *function2(void) {
int a = 3;
return &a;
}
void function1 (void){
void *temp = NULL;
temp = function2();
}
Or, alternatively, declare function2 before calling it
void *function2(void);
void function1(void) {
void *temp = NULL;
temp = function2();
}
void *function2(void) {
int a = 3;
return &a;
}
You have to declare your functions before you call them (preferably with prototype).
This answer is apart from truncation.
In function2() a is local variable. Here scope and lifetime od a limited to the function2. So returning the address to other function is illegal. It will cause undefined behavior. Please pay more attention to learn storage class in C
Consider the following code that takes the function f(), copies the function itself in its entirety to a buffer, modifies its code and runs the altered function. In practice, the original function that returns number 22 is cloned and modified to return number 42.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENOUGH 1000
#define MAGICNUMBER 22
#define OTHERMAGICNUMBER 42
int f(void)
{
return MAGICNUMBER;
}
int main(void)
{
int i,k;
char buffer[ENOUGH];
/* Pointer to original function f */
int (*srcfptr)(void) = f;
/* Pointer to hold the manipulated function */
int (*dstfptr)(void) = (void*)buffer;
char* byte;
memcpy(dstfptr, srcfptr, ENOUGH);
/* Replace magic number inside the function with another */
for (i=0; i < ENOUGH; i++) {
byte = ((char*)dstfptr)+i;
if (*byte == MAGICNUMBER) {
*byte = OTHERMAGICNUMBER;
}
}
k = dstfptr();
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
The code now relies on just guessing that the function will fit in the 1000 byte buffer. It also violates rules by copying too much to the buffer, since the function f() will be most likely a lot shorter than 1000 bytes.
This brings us to the question: Is there a method to figure out the size of any given function in C? Some methods include looking into intermediate linker output, and guessing based on the instructions in the function, but that's just not quite enough. Is there any way to be sure?
Please note: It compiles and works on my system but doesn't quite adhere to standards because conversions between function pointers and void* aren't exactly allowed:
$ gcc -Wall -ansi -pedantic fptr.c -o fptr
fptr.c: In function 'main':
fptr.c:21: warning: ISO C forbids initialization between function pointer and 'void *'
fptr.c:23: warning: ISO C forbids passing argument 1 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:23: warning: ISO C forbids passing argument 2 of 'memcpy' between function pointer and 'void *'
/usr/include/string.h:44: note: expected 'const void * __restrict__' but argument is of type 'int (*)(void)'
fptr.c:26: warning: ISO C forbids conversion of function pointer to object pointer type
$ ./fptr
Hello 42!
$
Please note: on some systems executing from writable memory is not possible and this code will crash. It has been tested with gcc 4.4.4 on Linux running on x86_64 architecture.
You cannot do this in C. Even if you knew the length, the address of a function matters, because function calls and accesses to certain types of data will use program-counter-relative addressing. Thus, a copy of the function located at a different address will not do the same thing as the original. Of course there are many other issues too.
In the C standard, there is no notion of introspection or reflection, thus you'd need to devise a method yourself, as you have done, some other safer methods exists however.
There are two ways:
Disassemble the function (at runtime) till you hit the final RETN/JMP/etc, while accounting for switch/jump tables. This of course requires some heavy analysis of the function you disassemble (using an engine like beaEngine), this is of course the most reliable, but its slow and heavy.
Abuse compilation units, this is very risky, and not fool proof, but if you know you compiler generates functions sequentially in their compilation unit, you can do something along these lines:
void MyFunc()
{
//...
}
void MyFuncSentinel()
{
}
//somewhere in code
size_t z = (uintptr_t)MyFuncSentinel - (uintptr_t)MyFunc;
uint8_t* buf = (uint8_t*)malloc(z);
memcpy(buf,(char*)MyFunc,z);
this will have some extra padding, but it will be minimal (and unreachable). although highly risky, its a lot faster that the disassemble method.
note: both methods will require that the target code has read permissions.
#R.. raises a very good point, your code won't be relocatable unless its PIC or you reassasmble it in-place to adjust the addresses etc.
Here is a standards compliant way of achieving the result you want:
int f(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = f(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
Now, you may have lots of uses of f() all over the place with no arguments and not want to go through your code changing every one, so you could do this instead
int f()
{
return newf(MAGICNUMBER);
}
int newf(int magicNumber)
{
return magicNumber;
}
int main(void)
{
k = newf(OTHERMAGICNUMBER);
/* Prints the other magic number */
printf("Hello %d!\n", k);
return 0;
}
I'm not suggesting this is a direct answer to your problem but that what you are doing is so horrible, you need to rethink your design.
Well, you can obtain the length of a function at runtime using labels:
int f()
{
int length;
start:
length = &&end - &&start + 11; // 11 is the length of function prologue
// and epilogue, got with gdb
printf("Magic number: %d\n", MagicNumber);
end:
return length;
}
After executing this function we know its length, so we can malloc for the right length, copy and editing the code, then executing it.
int main()
{
int (*pointerToF)(), (*newFunc)(), length, i;
char *buffer, *byte;
length = f();
buffer = malloc(length);
if(!buffer) {
printf("can't malloc\n");
return 0;
}
pointerToF = f;
newFunc = (void*)buffer;
memcpy(newFunc, pointerToF, length);
for (i=0; i < length; i++) {
byte = ((char*)newFunc)+i;
if (*byte == MagicNumber) {
*byte = CrackedNumber;
}
}
newFunc();
}
Now there's another bigger problem though, the one #R. mentioned. Using this function once modified (correctly) results in segmentation fault when calling printf because the call instruction has to specify an offset which will be wrong. You can see this with gdb, using disassemble f to see the original code and x/15i buffer to see the edited one.
By the way, both my code and yours compile without warnings but crash on my machine (gcc 4.4.3) when calling the edited function.
I want to the know the problems with the code presented below. I seem to be getting a segmentation fault.
void mallocfn(void *mem, int size)
{
mem = malloc(size);
}
int main()
{
int *ptr = NULL;
mallocfn(ptr, sizeof(ptr));
*ptr = 3;
return;
}
Assuming that your wrapper around malloc is misnamed in your example (you use AllocateMemory in the main(...) function) - so I'm taking it that the function you've called malloc is actually AllocateMemory, you're passing in a pointer by value, setting this parameter value to be the result of malloc, but when the function returns the pointer that was passed in will not have changed.
int *ptr = NULL;
AllocateMemory(ptr, sizeof(ptr));
*ptr = 3; // ptr is still NULL here. AllocateMemory can't have changed it.
should be something like:
void mallocfn(void **mem, int size)
void mallocfn(int **mem, int size)
{
*mem = malloc(size);
}
int main()
{
int *ptr = NULL;
mallocfn(&ptr, sizeof(ptr));
*ptr = 3;
return;
}
Because you need to edit the contents of p and not something pointed b p, so you need to send the pointer variable p's address to the allocating function.
Also check #Will A 's answer
Keeping your example, a proper use of malloc would look more like this:
#include <stdlib.h>
int main()
{
int *ptr = NULL;
ptr = malloc(sizeof(int));
if (ptr != NULL)
{
*ptr = 3;
free(ptr);
}
return 0;
}
If you're learning C I suggest you get more self-motivated to read error messages and come to this conclusion yourself. Let's parse them:
prog.c:1: warning: conflicting types for built-in function ‘malloc’
malloc is a standard function, and I guess gcc already knows how it's declared, treating it as a "built-in". Typically when using standard library functions you want to #include the right header. You can figure out which header based on documentation (man malloc).
In C++ you can declare functions that have the same name as already existing functions, with different parameters. C will not let you do this, and so the compiler complains.
prog.c:3: warning: passing argument 1 of ‘malloc’ makes pointer from integer without a cast
prog.c:3: error: too few arguments to function ‘malloc’
Your malloc is calling itself. You said that the first parameter was void* and that it had two parameters. Now you are calling it with an integer.
prog.c:8: error: ‘NULL’ undeclared (first use in this function)
NULL is declared in standard headers, and you did not #include them.
prog.c:9: warning: implicit declaration of function ‘AllocateMemory’
You just called a function AllocateMemory, without telling the compiler what it's supposed to look like. (Or providing an implementation, which will create a linker error.)
prog.c:12: warning: ‘return’ with no value, in function returning non-void
You said that main would return int (as it should), however you just said return; without a value.
Abandon this whole idiom. There is no way to do it in C without making a separate allocation function for each type of object you might want to allocate. Instead use malloc the way it was intended to be used - with the pointer being returned to you in the return value. This way it automatically gets converted from void * to the right pointer type on assignment.