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.
Related
So, I am just trying to wrap my head around "pointer function that returns a pointer to an array"... but to start off slowly, I had to understand this:
void Print(const char c){
printf("\nPrint: %c\n", c);
}
int main () {
void (*FunctionPointer)(const char);
FunctionPointer = &Print;
FunctionPointer('a');
}
Which I do - pretty easy to guess what is going on... FunctionPointer just points to the location where the Print function "resides". Instead of jumping to a specific memory address (stored on a register) of a specific function, I can now be more flexible and point to any function that I want to access.
But I am stuck with the following...
int main () {
int (*FunctionPointer())[];
}
Now it seems that the function that is pointed by FunctionPointer, can in fact return a pointer to an array of type int. The compiler accepts the second line - so far so good - and I also understand the concept... but I am getting stuck regarding the implementation.
FunctionPointer needs - once again, to point to a function. That function can indeed return a pointer that points to an array of type int... soooooo:
int *Array(){
int ar[2] = {5,6};
return ar;
}
int main () {
int (*FunctionPointer())[];
FunctionPointer = &Array;
}
However, the last piece of code is just not accepted by the compiler.... So, what gives?
With
int (*FunctionPointer())[];
you've declared FunctionPointer as a function returning a pointer to an array of int -- not a function pointer. You want
int *(*FunctionPointer)();
If you use [] here, you'll get an error, as functions can't return arrays -- arrays are not first class types -- and unlike with function parameters, arrays will not be silently converted to pointers when used as the return value of a function type. With that, you'll still get the warning
t.c:3:12: warning: function returns address of local variable [-Wreturn-local-addr]
return ar;
^~
which is pretty self-explanatory
You have declared the array of function pointers. Arrays can't be assignable. Functions can't return arrays. You might wish
int* (*FunctionPointer)();
FunctionPointer = &Array;
Function pointers are much easier when you use typedefs. You can simply use the same notation as "normal" data pointers.
// func is a function type. It has one parater and returns pointer to int
typedef int *func(const char);
// funcptr is a pointer to func
func *funcptr;
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.
I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting. So according to me answer should be option A. But in official GATE-2017 exam answer key, answer is given D. So am i wrong ? how ?
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int *assignval(int *x, int val){
*x = val;
return x;
}
void main(){
clrscr();
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
x = (int *)malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,10);
}
printf("%d\n",*x);
free(x);
getch();
}
(A) compiler error as the return of malloc is not typecast
appropriately.
(B) compiler error because the comparison should be made as x==NULL
and not as shown.
(C) compiles successfully but execution may result in dangling
pointer.
(D) compiles successfully but execution may result in memory leak.
In my opinion option D is only correct when int *x = (int *)malloc(sizeof(int)); is used.
There's no right answer among the choices offered.
The immediately obvious problems with the code, under assumption that the code is supposed to be written in standard C:
Standard library does not have <conio.h> header or <iostream.h> header.
void main() is illegal. Should be int main(). Even better int main(void)
clrscr(), getch() - standard library knows no such functions.
The second malloc leaks memory allocated by the first one (assuming the first one succeeds).
Result of second malloc is explicitly cast - bad and unnecessary practice.
The statement :
int *x = malloc(sizeof(int));
will not lead to compile error, as it declares x as a pointer to int and initializes it right afterwards. It did not have type void beforehand.
The statement :
x = (int *)malloc(sizeof(int));
causes a possible memory leak, as it reallocates the memory which is already allocated for x.
NOTE : However none of this answers is completely correct. This code will not compile for various reasons.
If this is your code, change :
void main()
to :
int main(void)
and also see why you should not cast the result of malloc.
Apart from that, clrscr(), getch(), <conio.h> and <iostream.h> are not recognized by standard library.
I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting.
There's more than a little debate about whether or not to cast malloc, but it's a stylistic thing. void * is safely promoted to any other pointer.
ISO C 6.3.2.3 says...
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Whatever you choose, pick one and stick with it.
The memory leak is here:
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
// Memory leak
x = (int *)malloc(sizeof(int));
The first malloc points x at allocated memory. The second malloc can only happen if the first succeeded (if x is true). The pointer to the memory allocated by the first malloc is lost.
Using a new variable would fix the leak, keeping in mind that the code is nonsense.
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
int *y = malloc(sizeof(int));
if(NULL==y) return;
y = assignval(y,10);
free(y);
}
As a side note, void main() is technically not a violation of the ISO C standard, it is "some other implementation-defined manner".
5.1.2.2.1 says:
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
int main(int argc, char argv[]) { / ... */ }
or equivalent;) or in some other implementation-defined manner.
I'm guessing you're using a Windows compiler, that would be the "some other implementation". clang considers it an error.
test.c:8:1: error: 'main' must return 'int'
void main(){
^~~~
int
1 error generated.
you should never forget that a void * pointer can be assigned to all type of pointers. in IDEs like visual studio, you get a compile error if you do not perform casting while assigning a void * to <>. for example:
float *ptr = malloc(sizeof(float));//compile error in visual studio.
but if you compile it with GCC without typecasting, you won't get a compile error.
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
I'm trying to compile but getting the errors
error: expected expression before 'void'
warning: passing argument 3 of 'pthread_create' from incompatible pointer type [enabled by default] used [-Wunused-but-set-variable]
I type casted the struct to void* so it should work.
In the global variable section I have
struct threadArgs
{
char** str;
int length;
};
struct threadArgs arguments;
The lines around the error are here
arguments.str = str;
arguments.length = linesRead;
for(int i = 0; i < lettersInAlpha; i++)
errCode[i] = pthread_create(&letter[i], NULL, &findMatch, (*void)&arguments);
the prototype for findMatch is void findMatch(char **str, const int length);
Also I think I'm doing the right thing by passing the arrays address, right?
Basically any code can be changed, so findMatch() can be modified as needed.
Your function must be conforming to the requirements of pthreads as a valid thread-proc. Part of the compliance is the signature. it must be of the form void *func(void*). in other words your function must:
return void*
take a single void* parameter.
The argument address you provide at the end is passed to your thread proc, and you're responsible for unpacking your own parameters from there.
Trying to minimize the changes you need for findMatch, declare your thread function like this:
void * findMatch(void* pv)
{
struct threadArgs * argsp = pv;
char **str = argsp->str;
const int length = argsp->length;
// the rest of your code.
return NULL;
}
Note: your code hints at something else that may be an issue. arguments is a global. This means that once you start a thread, if you modify arguments for preparation for the next thread, you have created a race condition where your modifications will potentially race with the initial thread's access of that memory. This isn't an issue in your code as-is, because you make no modifications to arguments from thread-to-thread creation. But if you ever do, consider allocating a separate arguments variable to be sent to each thread, so that thread "owns" it, and only it.