GCC / weak symbol function: Why does this segfault? - c

For unit testing I'd like to replace a function from "outside". Normally, I'm using the wrapping mechanism - but unfortunately this does not work for calls to the function from within the same compilation unit.
My idea was to mark the function as "weak" so I am able to reimplement it in a testing application. Generally this works using the following code:
File myfunctions.c (this is the code under test):
#include "myfunctions.h"
int weakFunction(int param) __attribute__((weak));
int weakFunction(int param)
{
return 2*param;
}
int myfunction(int param)
{
int result = weakFunction(param);
return (result == (2*param)) ? 1:0;
}
File main.c
#include "myfunctions.h"
int weakFunction(int param)
{
return 3*param;
}
int main()
{
return myfunction(5);
}
This example works as expected - when I remove weakFunction from main.c, the program returns 1, when I add weakFunction the program returns 0. Looks good at this point.
But as soon as I change the order within myfunctions.c as follows, the resulting program crashes with a segmentation fault:
File myfunctions.c (modified order):
#include "myfunctions.h"
int weakFunction(int param) __attribute__((weak));
int myfunction(int param)
{
int result = weakFunction(param);
return (result == (2*param)) ? 1:0;
}
int weakFunction(int param)
{
return 2*param;
}
Any idea? What could be the reason for the crash?
I am using GCC 4.8.1 (MinGW w64 build) on Windows 7.
Thanks for any help!
Florian

Related

Why is Cod::Blocks giving me Null instead of a input char?

Source Code:
#3 main.c
# include "func.h"
int main(void) {
func();
return 0;
}
#3 func.h
#include <stdio.h>
void inputName();
void printName();
void func();
#3 func.c
#include "func.h"
char GLOBAL_NAME;
void inputName() {
scanf("%s", &GLOBAL_NAME);
}
void printName() {
printf("Your name is: %s.\n", &GLOBAL_NAME);
}
void func(void) {
inputName();
printName();
}
Out Put:
Your name is: (null).
I used https://www.online-cpp.com/online_c_compiler with the same code, it works fine on the online compiler. but when I try to use it on Code::Blocks it shows me:
Your name is: (null).
Don't know what's the problem, Could it be a compiler thing?
I'm using a windows machine for Code::Blocks using GCC I think as the compiler.
Initialize your char variable with a length and since you have not initialized it with a length it returns NULL.
char GLOBAL_NAME[30];

Why isn't my function invoked? I don't understand why a declaration is expected

Hello folks out there,
this is my code:
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sqlite3.h"
#include "db_typedefs.h"
#include "operations.h"
int main(){
printf("Text\n");
int f = 3;
void add_mini(3);
}
operations.h
#ifndef ADD_OPERATIONS_H_INCLUDED
#define ADD_OPERATIONS_H_INCLUDED
void add_mini(int flag);
#endif // ADD_OPERATIONS_H_INCLUDED
operations.c
void add_mini(int flag)
{
int rc;
rc = flag;
printf("%i\n", rc);
}
Operations.c has also libraries included similar to main.c.
Compiler Error
error: expected declaration specifiers or '...' before numeric constant
regarding to void add_mini(3)
It seems like I'm unable to pass a simple integer value. While debugging it's even skipping the add_mini line.
Do you have any idea what's going on?
The whole code is embedded in a larger query to determine typed orders but this works fine. I just can't pass this simple integer value.
Thanks in advance.
When you use
void add_mini(3);
the compiler thinks it is a function declaration, not a function call. The argument 3 is not valid for a function declaration. Hence, the compiler complains.
Remove the void part to call the function.
int main(){
printf("Text\n");
int f = 3;
add_mini(3);
}
or, since you have initialized f to 3,
int main(){
printf("Text\n");
int f = 3;
add_mini(f);
}
Call the function like so: add_mini(3); rather than void add_mini(3);
Remove the word void for calling add_mini from main.c :
add_mini(3);
Or
(void)add_mini(3);

C, how can a macro register a unittest for execution?

How can libraries such as GTest use a single macro G_TEST(...) to both define the function and register it as a test function? I'm looking for a way to do the same for my C99 project.
Example
#include <stdio.h>
#include "my_test_header_that_doesnt_exist.h"
TEST_MACRO(mytest)
{
printf("Hello, world\n");
return 0;
}
TEST_MACRO(mytest2)
{
printf("Hello, world 2\n");
return 2;
}
int main(int argc, char** argv)
{
RUN_TESTS();
return 0;
}
Can't figure out how to register the tests so they are known from RUN_TESTS()
By passing an -E option to g++ you can inspect the code after preprocessing. Example code using the GTest library:
#include <gtest/gtest.h>
TEST(testcase, mytest) {
// Code
}
int main() {
return RUN_ALL_TESTS();
}
And compiling it with:
g++ -E -Igtest_include_path example.cpp -oexample_preprocessed.cpp
The TEST macro expanded to:
class testcase_mytest_Test : public ::testing::Test {
public:
testcase_mytest_Test() {}
private:
virtual void TestBody();
static ::testing::TestInfo* const test_info_ __attribute__ ((unused));
testcase_mytest_Test(testcase_mytest_Test const &);
void operator=(testcase_mytest_Test const &);
};
::testing::TestInfo* const testcase_mytest_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "testcase", "mytest", __null, __null, ::testing::internal::CodeLocation("cpp_test.c", 3), (::testing::internal::GetTestTypeId()), ::testing::Test::SetUpTestCase, ::testing::Test::TearDownTestCase, new ::testing::internal::TestFactoryImpl< testcase_mytest_Test>);
void testcase_mytest_Test::TestBody() {
// Code
}
And RUN_ALL_TESTS() is not a macro:
inline int RUN_ALL_TESTS() {
return ::testing::UnitTest::GetInstance()->Run();
}
So it's in fact a complicated chain of preprocessor macros that make up a class out of your test case, and does all sorts of things to link it to the machinery that runs it.
Obviously you are not going to be able to do it like this in a C99 project, as GTest is a C++ library, and it heavily relies on C++ features to do the job.
If you wish to understand how it works fully, you should check out the GTest code in its repository: https://github.com/google/googletest

How to use macro for calling function?

I want to call function according to func_name string.
My code is here below:
#define MAKE_FUNCNAME func_name##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
char func_name[30] = "print_";
call_func(MAKE_FUNCNAME);
return 0;
}
But this code doesn't work. I want code to work like call_func(print_hello). But preprocessor treated my code like call_func("print_hello"). How to use macro in C to make my exception? Or is it not possible using C?
Then problem with your code is that the value of func_name is only known at run-time.
You can however to it like this:
#define MAKE_FUNCNAME(FUNCNAME) FUNCNAME##hello
void call_func(void* (*func)(void))
{
func();
}
void *print_hello(void)
{
printf("print_hello called\n");
}
int main(void)
{
call_func(MAKE_FUNCNAME(print_));
return 0;
}
But it is not possible to use a string value within macro parameters like in your code snippet.
If you want to get call functions with their names using string values you can use a table to store function pointer with function names like this:
struct {
const char *name;
void (*ptr)(void);
};
You can use an array of this structure to find out the function pointer at run-time using a string value. This is the most common solution to using run-time strings to call functions using their names.
You can't do that. The value of func_name is known at run-time (even though it is a const char *), while you want to determine what to call at precompile-time. You should turn your cpp macro into something different (such as an if/switch statement or using an indirection).
Maybe you could have a look to dlsym().
Not sure I really understand the question, but if you want to "build" the function name at runtime and then call the corresponding function, it should be possible with dlsym()
/* compile with: gcc example.c -ldl -rdynamic */
#include <dlfcn.h>
#include <stdio.h>
int print_hello(void)
{
return printf("hello\n");
}
int main(int argc, char *argv[])
{
const char *name = "print_hello";
if (argc == 42)
print_hello(); /* for compiler not to remove print_hello at
* compile time optimisation in this example*/
void *handle = dlopen(NULL /* self */, RTLD_NOW);
int (*f)(void) = dlsym(handle, name);
f();
return dlclose(handle);
}

Undefined reference to "function"

So I have this very simple program but I can't seem to get rid of a simple error.
I have a Header file with this
#ifndef FUNCTIONLOOKUP_H_INCLUDED
#define FUNCTIONLOOKUP_H_INCLUDED
enum functions
{
foo,
bar
};
//predefined function list
int lookUpFunction(enum functions);
#endif // FUNCTIONLOOKUP_H_INCLUDED
And in the src file i have the definition of lookUpFunction
Now when I call the lookUpFunction() from my main where I included the header file it gives me a undefined reference to it. The other awnsered questions where of no help.
#include <stdio.h>
#include <stdlib.h>
#include "FunctionLookUp.h"
int main()
{
lookUpFunction(foo); <---
return 0;
}
Function implementation
#include <stdio.h>
#include "FunctionLookUp.h"
typedef void (*FunctionCallback)(int);
FunctionCallback functionList[] = {&foo, &bar};
void foo(int i)
{
printf("foo: %d", i);
}
void bar(int i)
{
printf("bar: %d", i);
}
int lookUpFunction(enum functions)
{
int test = 2;
//check if function ID is valid
if( functions >= sizeof(functionList))
{
printf("Invalid function id"); // error handling
return 0;
}
//call function
functionList[functions](test);
return 1;
}
I can't seem to figure out where this error comes from.
You must have some file similar to:
/* FunctionLookUp.c */
#include "FunctionLookUp.h"
int lookUpFunction(enum functions)
{
/* code ... */
return x;
}
somewhere in order to solve your problem
You never show code that implements the function.
So it's most likely that what you're seeing is a linker error, the call itself is fine but the linker cannot find the code to call, so it throws an error.
Just declaring a function can't magically make it appear from somewhere, you must write the actual function too.

Resources