I'm having some trouble with function pointers and passing them as inputs to other functions in C++. I've written some simplified code that sums up the trouble that I'm having. I have two .cpp files as below
functions.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
typedef double(*real_function)(double);
double one(double x) {
return double(1);
}
void applyfunction(int length, real_function f, double* result) {
int j;
result[0] = 0;
for (j = 1; j < length; j++) {
result[j] = f(result[j - 1]);
}
}
Source.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
typedef double(*real_function)(double);
real_function one;
void applyfunction(int, real_function, double*);
int main(void) {
double* result;
result = (double*)calloc(10, sizeof(double));
applyfunction(10, one, result);
return(0);
}
When I compile this, I get the following error in Visual Studio 2015
Exception thrown at 0x00000000 in Project3.exe: 0xC0000005: Access violation executing location 0x00000000.
If there is a handler for this exception, the program may be safely continued.
What is going wrong? The funny thing is that if we define those functions one and applyfunction in the source.cpp file (i.e. put all code in a single file), things seem to work. So, I think that it must be something very simple that I am getting wrong. Thank you for any help.
real_function one;
This creates a global variable one which is initialized to a null pointer.
applyfunction(10, one, result);
You then pass that null pointer to applyfunction...
result[j] = f(result[j - 1]);
...wherein you try to call it, generating the null pointer exception.
To fix this, don't create a variable one in Source.cpp. Instead, add a prototype that matches the definition in functions.cpp. In other words, replace real_function one; with
double one(double x);
real_function one;
doesn't declare the function one in the other file; it defines a function pointer called one. Because it's global (and thus has static storage), it's initialized to null. Your program crashes because it's trying to call a null pointer.
One way to fix this is to change
typedef double(*real_function)(double);
to
typedef double real_function(double);
This way real_function actually names a function type (not a pointer).
Related
I am compiling with g ++ an application that calls some functions defined in a "C" library.
Some of the functions that I need to call are defined as static in the original ".c" file (I know that when a function is defined static it is so that it is not called from outside of that file, but despite that, I need to call them from outside of the same).
I am going to execute them from outside that file using pointers to functions and to see how they work, I have prepared this example, where I want to execute in file_2.c the static functions fun5 and fun6 defined in file_1.c
file_1.h
--------
#ifndef FILE_1_H
#define FILE_1_H
int (*getPtrFun6(void*))(int,char,char*);
#endif
file_1.c
--------
#include <stdio.h>
int(*ptr_fun5)(int,int);
static int fun5(int p1, int p2)
{
printf("fun5 called.\n");
ptr_fun5 = &fun5;
return p1 + p2;
}
static int fun6(int p1, char p2, char* p3)
{
printf("fun6 called with p1 = %d, p2 = %c, p3 = %s.\n", p1, p2, p3);
return p1;
}
int (*getPtrFun6(void*))(int,char,char*)
{
return fun6;
}
file_2.c
--------
#include <stdio.h>
#include <cstring>
#include "file_1.h"
extern int(*ptr_fun5)(int,int);
extern int(*ptr_fun6)(int,char,char*);
int main(void)
{
int returnValue = 0;
// To run fun5
returnValue = (ptr_fun5)(15, 32);
printf ("Returns %d\n", returnValue);
// To run fun6
char myString[50];
memset(myString,0,50);
strncpy(myString,"THIS IS OK",10);
ptr_fun6 = getPtrFun6();
returnValue = (ptr_fun6)(32, 'v', myString);
printf ("Returns %d\n", returnValue);
return 0;
}
I compile the program with the command:
g++ file_2.c file_1.c -o static_example
As you can see from the source code, I have tried two different ways to use a pointer to a static function.
If I comment on everything about fun6 in the source code, compile it and run it (just call fun5) I get the error "Segmentation fault".
On the other hand, if I comment on everything related to fun5 in the source code and leave only fun6, when compiling the program, I get these errors:
file_2.c: In function ‘int main()’:
file_2.c:20:25: error: too few arguments to function ‘int (* getPtrFun6(void*))(int, char, char*)’
ptr_fun6 = getPtrFun6();
^
In file included from file_2.c:4:
file_1.h:4:7: note: declared here
int (*getPtrFun6(void*))(int,char,char*);
^~~~~~~~~~
I have looked at various forums and tutorials on the web and I don't see what the error is, so I would need some help on the correct way to use the pointers to fun5 and fun6.
(just call fun5) I get the error "Segmentation fault".
Because fun5 is uninitialized, it doesn't point anywhere.
when compiling the program, I get these errors: ... error: too few arguments to function
So why did you declare it to take a void* as parameter? If you don't want that, then it should be void.
General advise:
Get rid of global variables with extern.
Use typedef whenever dealing with function pointers, so that the code can be read by humans. Evidentally, int (*getPtrFun6(void*))(int,char,char*) isn't readable even by yourself.
int (*getPtrFun6(void*))(int,char,char*);
Confusing syntax is leading to wrong prototype and declaration.
The easy to read way (function pointers are same as "normal" pointers):
typedef int fun6type(int, char, char *);
fun6type *getPtrFun6(void);
fun6type *getPtrFun6(void)
{
return fun6;
}
Hard to read way:
int (*getPtrFun6_1(void))(int, char, char *);
int (*getPtrFun6_1(void))(int, char, char *)
{
return fun6;
}
int foo(void)
{
int (*f)(int, char, char *) = getPtrFun6_1();
return f(1, 'a', "Test");
}
Test it yourself
https://godbolt.org/z/erh63jTc8
If I comment on everything about fun6 in the source code, compile it
and run it (just call fun5) I get the error "Segmentation fault".
Function pointer has to reference a valid function before it is dereferenced (called) as any other pointer. Your one is not initialized and it is not referencing a valid function.
BTW It is rather C code (not C++). In C++ use of function pointers (and generally pointers) should be avoided.
returnValue = (ptr_fun5)(15, 32); does not work because ptr_fun5 is initialized to a null pointer and is not given any other value until the statement ptr_fun5 = &fun5; inside fun5 is executed, which does not happen until fun5 is called.
One way to fix that is to delete int(*ptr_fun5)(int,int); and put int (*ptr_fun5)(int, int) = fun5; after the declaration of fun5. Then it will be initialized to the address of fun5.
main.h: header
#ifndef _MAIN_H
#define _MAIN_H
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct ComplexNum
{
double real;
double img;
}mc;
char *JustShow(mc );
#endif // _MAIN_H
cal.cpp : function defined in another file called
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "main.h"
char *JustShow(mc a)
{
char str1[100];
char str2[100];
char str3 [100];
sprintf(str1,"%f",a.real);
sprintf(str2,"%f",a.img);
strcat(str1," + ");
strcat(str1,str2);
strcat(str1,"i");
return(str1);
}
I tried to use the JustShow function in another file, but the compiler said undefined reference to 'JustShow'
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "main.h"
int main()
{
mc y;
y.img = 4;
y.real = 3;
printf("%s",JustShow(y));
}
I am so confused why can't I use the function JustShow when I had already added "main.h". I am also confused why should we define the functions in the source file instead of the header.
I'm sorry if this is the basic knowledge I should learn about and not ask others.
I'm going to call the third piece of code "main.cpp".
why can't I use the function JustShow when I had already added "main.h".
Header files only inform a compiler that a function, variable or constant exist. You need to compile cal.cpp with main.cpp: g++ main.cpp cal.cpp -o main
I am also confused why should we define the functions in the source file instead of the header.
It makes code more organised.
It speeds up compile time.
You can read more about header files here
Some advice for your code:
Function JustShow is incorrect. Arrays are just pointers and you are returning a pointer to a local variable that are deleted after function returns. It means that it will be overwritten and you will lose data there (and trying to write there may crash your program). In order to make it work you can:
Give an array as an argument to the function. Then we would have void JustShow(mc a, char* str1);
create new array with new (or malloc if you wirte in C, not C++).
You don't need to concat so much. sprintf can do all of that:
void JustShow(mc a, char* str1) {
sprintf(str1,"%f + %fi", a.real, a.img);
}
Yesterday I asked a question about this problem, but I wasn't able to give a MVCE. I've managed to reproduce this with a simple program. The problem is with using an std::list as a static inline declaration in a class. Microsoft Visual Studio does support this new C++17 feature. It had some bugs as of March, but as far as I know they've been fixed since. Here are instructions of how I can get this problem, this happens in debug mode.
In main.cpp
#include <iostream>
#include "header1.h"
int main()
{
return 0;
}
In header1.h:
#include <list>
struct Boo
{
static inline std::list<int> mylist;
};
In anotherCPP.cpp
#include "Header1.h"
When the program exits main() it destroys all the static objects and throws an exception.
If this doesn't crash, maybe on your system the compiler/linker optimised some code out, so you can try making main.cpp and anotherCPP.cpp do something. In anotherCPP.cpp:
#include <iostream>
#include "Header1.h"
void aFunction()
{
std::cout << Boo::mylist.size();
}
And make main.cpp:
#include <iostream>
#include "Header1.h"
void aFunction();
int main()
{
std::cout << Boo::mylist.size();
afunction();
return 0;
}
When the program exits I get an exception here when the std::list is being cleared. Here is the Visual Studio debug code where it crashes:
for (_Nodeptr _Pnext; _Pnode != this->_Myhead(); _Pnode = _Pnext)
{ // delete an element
_Pnext = _Pnode->_Next; // Here: Exception thrown:
// read access violation.
// _Pnode was 0xFFFFFFFFFFFFFFFF.
this->_Freenode(_Pnode);
}
This happens only if I declare the static inline std::list< int > mylist in the class. If I declare it as static std::list< int > mylist in my class and then define it separately in one .cpp as std::list< int > Boo::mylist; it works fine. This problem arises when I declare the std::list static inline and I include the header for the class in two .cpp files.
In my project I have stepped through the std::list clear loop from above, I took note of the "this" pointer address. I stepped through the loop as it freed nodes in my list. It then came back to free other std::lists, including in std::unordered_map (as they also use std::lists from the looks of it). Finally when the read access exception is thrown and _Pnode is an invalid pointer address, I noticed the "this" pointer address is the same as the "this" pointer address when clearing std::list< int > mylist, which makes me think that it's trying to delete it twice, and probably why it's crashing.
I hope someone can reproduce this, I'm not sure what this is, if it's a bug or something I'm doing wrong. Also this happens for me in 32 and 64 bit, but only in debug mode, because the node freeing loop I provided is under a macro:
#if _ITERATOR_DEBUG_LEVEL == 2
This issue was filed as a bug here under the title "Multiple initializations of inline static data member in Debug mode".
This was found in Visual Studio 2017 version 15.7.
The VS compiler team has accepted this and have fixed the problem in an upcoming release.
I am trying to define a variable from an external library in C++, Visual Studio 2010. It only works when I put it outside of the main function.
This code crashes:
#include "StdAfx.h"
#include <ogdf\basic\Graph.h>
#include <ogdf\basic\graph_generators.h>
int main()
{
ogdf::Graph g;
ogdf::randomSimpleGraph(g, 10, 20);
return 0;
}
It gives me an unhandheld exception: Access violation.
However, if it is outside main function, it works without any problem:
#include "StdAfx.h"
#include <ogdf\basic\Graph.h>
#include <ogdf\basic\graph_generators.h>
ogdf::Graph g;
int main()
{
ogdf::randomSimpleGraph(g, 10, 20);
return 0;
}
Do you have any how do I fix that? I assume, that it is caused by some kind of linking problem.
EDIT: It looks like the problem is not the initialization of the variable. It throws an exception, when the application exits.
int main()
{
ogdf::Graph g; // No problem
ogdf::randomSimpleGraph(g, 10, 20); // No problem
int i; // No problem
std::cin>>i; // No problem
return 0; // Throws an exception after read i;
}
Call stack:
The output is:
First-chance exception at 0x0126788f in graphs.exe: 0xC0000005: Access violation writing location 0x00000000.
Unhandled exception at 0x0126788f in graphs.exe: 0xC0000005: Access violation writing location 0x00000000.
Works on my machine™.
Esoteric errors like that are often a result of binary incompability. Basically, because of different compiler/preprocessor options, effective headers that your code and the library "see" are different.
For instance, if you have a library with following header code:
class Foo
{
#ifdef FOO_DEBUG
int debug_variable;
#endif
int variable;
};
Library function:
void bar(Foo& foo)
{
std::cout << foo.variable;
}
And client code:
Foo foo;
foo.variable = 666;
bar(foo);
If FOO_DEBUG is not in sync amongst client and the library, this will possibly crash and burn -- variable will have different expected offset.
In your case, I suspect one of the following may be true:
You have built the ogdf with different compiler than your code
If not, you ogdf and your code have different build configurations (Release vs Debug)
Both are debug, but you have defined OGDF_DEBUG (as recommended here)
You have different "Struct Member Alignment" setting
i am trying to make user threads in C++, so while trying to initialize them i am getting a compiler error :translate_address was not declared in this scope
#include <iostream>
#include <cstdlib>
#include <csignal>
#include <csetjmp>
#define JB_SP 6 //Location in the code
#define JB_PC 7 //Stack pointer
#define STACK_SIZE 10
typedef unsigned long address_t; //64bit address
sigjmp_buf jbuf[3];
char stack1[STACK_SIZE];
void f(){
}
void setup(){
unsigned int sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
pc = (address_t)f;
sigsetjmp(jbuf[0],1);
(jbuf[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(jbuf[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&jbuf[0]->__saved_mask);//empty saved signal mask
}
int main(){
return 1;
}
am i meant to include it some how? or is there a different problem?
thank you.
translate_address is not a Linux function. If you're referring to some kind of book or example code, it should explain where you're supposed to get this function from. If it doesn't, chances are it's not meant for Linux (or is a really, really bad reference/example).
Furthermore, you should NOT modify the contents of jmp_buf or sigjmp_buf directly. These are architecture and platform-dependent structures, and only the C library is allowed to mess with them. Since the contents of the structures are OS-dependent, if you're using a reference intended for some other OS when modifying sigjmp_buf, Bad Things will happen.
You should instead either use setcontext, getcontext, and makecontext for user threads (fibers) or pthread_create for OS-level threads.