Having link error and not sure how to solve it? - c

#include <stdio.h>
#include <stdbool.h>
int SmallerOf(int x, int y);
void TestCase(void)
{
int x, y, actual;
x = 3;
y = 4;
actual = 3;
int expected = SmallerOf(x, y);
if (actual == expected)
{
printf("PASS");
}
else
{
printf("FAIL");
}
}
Having an error with linker having a linker error message 2019. I tried to see if my linker under properties looking at something different or a certain file. It seems like everything is good and I a just look. What could be the cause of this when I haven't touched the linker directories? thank you
I have looked at properties and it seems to be fine and not sure what this error message means.

This is a (forward) declaration of a function:
int SmallerOf(int x, int y);
It makes a promise to the compiler that there will be a definition of the function later, so the compiler will not complain when you call it in your code - even if the compiler have even not seen the actual function definition yet.
When linking your final program, it will however not find this definition, hence you get a linker error. In order to fix the problem, provide a definition of the function too. Example:
int SmallerOf(int x, int y) {
return x < y ? x : y;
}
Your final program also needs a definition of the int main(void) or int main(int, char**) function in order to know where to start execution of the program.

Related

Putting error or warning message (extern variable)

My a.c file:
int sum(int a, int b) {
return a + b;
}
My b.c file:
#include<stdio.h>
extern int sum(int, int);
int main() {
printf ("%d", sum(2, 3));
return 0;
}
gcc a.c b.c -o output, working fine.
Let say tomorrow, I change the definition of "a.c file" sum function by increasing the argument to three. Like this,
int sum(int a, int b, int c) {
return a + b + c;
}
But forget to change the usage in b.c file (means I'm still using with two variable)
gcc a.c b.c -o output (doesn't give compilation error or warning mssg, printf gives wrong answer, obviously)
Now consider I'm working in huge set of c file and I cannot make new header file, because it will create unnecessary dependency problem which may take huge time to resolve.
What is the best way to throw error or even warning message in case the extern original definition is changed in terms of argument ?
Regards
What is the best way to throw error or even warning message in case the extern original definition is changed in terms of argument?
Neither compiler nor linker will object to that. You'll just find out at runtime (if you are lucky) when your program stops working.
If this was C++ then name mangling would allow the linker to reject such mal-formed programs. However, for C the linker only needs to find a symbol with the right name. It has no means of checking the signature.
Using header files is the accepted way to get the compiler to make sure you do things right. Repeating function declarations over and over throughout your program is usually a very bad idea. Whatever downsides you perceive to using header files pale into insignificance when compared to your proposed approach.
If you simply won't use header files, then you'll just have to always be right!
Normally editors like (SourceInsight,Sublime) have the options to browse the symbols. By using this option you can easily find function calls and prototype.
Compiler never generate warnings or error for your problem.Self contained header files are best option to avoid this situation.
The best thing to do is try to avoid "extern" and include the header file for sum(). Using header files and prototyping your functions will help the compiler catch these issues.
test.c:
#include <stdio.h>
#include "math.h"
int main(void)
{
printf("%d", sum(2, 3));
return 0;
}
math.h:
int sum(int a, int b, int c)
{
return (a + b + c);
}
output:
~]$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6:5: error: too few arguments to function ‘sum’
printf("%d", sum(2, 3));
^
In file included from test.c:2:0:
math.h:1:5: note: declared here
int sum(int a, int b, int c)

OpenCV Code Sample Error

I have written the following Code Sample that is supposed to create a peculiar-looking gradient and save it to a file specified by the user:
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
static IplImage *image = 0;
void main() {
char path[1024];
int x, y;
CvScalar scalar;
scanf("%s", path);
image = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
for (y = 0; y < 480; y++) {
for (x = 0; x < 640; x++) {
scalar = cvGet2D(image, x, y);
scalar.val[0]=(unsigned char)(x + y);
cvSet2D(image, x, y, scalar);
}
}
cvSaveImage(path, image, 0);
}
I compile it using: gcc opencv.c -o opencv `pkg-config --libs --cflags opencv` -lm and everything seems to be OK. However, during runtime (input: "sample.png"), I get the following error:
OpenCV Error: One of arguments' values is out of range (index is out of range) in cvPtr2D, file /builddir/build/BUILD/OpenCV-2.3.1/modules/core/src/array.cpp, line 1797
terminate called after throwing an instance of 'cv::Exception'
what(): /builddir/build/BUILD/OpenCV-2.3.1/modules/core/src/array.cpp:1797: error: (-211) index is out of range in function cvPtr2D
Aborted (core dumped)
Any help, please? Thanks in Advance! :)
cvGet2D and cvSet2D uses [row,column] convention like many other functions in opencv.
For further readings:
http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/
The cvGet2D and cvSet2D function take the row as the first argument, and the column as the second argument: you have the x and y arguments the wrong way round. Hence you are going outside the image. The call should be:
cvGet2D(image, y, x);

Variable declaration after goto Label

Today I found one interesting thing. I didn't know that one can't declare a variable after a goto label.
Compiling the following code
#include <stdio.h>
int main() {
int x = 5;
goto JUMP;
printf("x is : %d\n",x);
JUMP:
int a = 0; <=== giving me all sorts of error..
printf("%d",a);
}
gives errors like
temp.c: In function ‘main’:
temp.c:7: error: expected expression before ‘int’
temp.c:8: error: ‘a’ undeclared (first use in this function)
temp.c:8: error: (Each undeclared identifier is reported only once
temp.c:8: error: for each function it appears in.)
Now what is the logic behind that? I heard that one cannot create variables inside the case statements of switch. Since JUMP is inside the same scope (the scope of main function, in my case) of the goto statement, I believe that scope is not an issue here. But then, why am I getting this error?
The syntax simply doesn't allow it. §6.8.1 Labeled Statements:
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
Note that there is no clause that allows for a "labeled declaration". It's just not part of the language.
You can trivially work around this, of course, with an empty statement.
JUMP:;
int a = 0;
You want a semi-colon after the label like this:
#include <stdio.h>
int main() {
int x = 5;
goto JUMP;
printf("x is : %d\n",x);
JUMP: ; /// semicolon for empty statement
int a = 0;
printf("%d",a);
}
Then your code compiles correctly for the C99 standard, with gcc -Wall -std=c99 -c krishna.c (I'm using GCC 4.6 on Debian/Sid/AMD64).
Simple explanation, other than the spec says not, is that the compiler is exepecting the code after the goto to be something that compiles into an operation which it can then calculate the offset of, and is kicking because your variable declaration isn't a statement/block that it can compile into such an offset.
My gcc version (4.4) is giving this compile error:
t.c:7: error: a label can only be part of a statement and a declaration is not a statement
. This error-message says it all.
If you know why you can't create variables inside case statement of switch, basically its the same reason why you cant do this too. As a fix, you can try this,
#include <stdio.h>
int main() {
int x = 5;
goto JUMP;
printf("x is : %d\n",x);
JUMP:
{ //Note this
int a = 0; // <=== no more error..
printf("%d",a);
} //Note this
}
Well, first you should be consistent. It's either LABEL or label. Second, label is a part of the statement and the declaration doesn't answer the description enough.
You can replace LABEL: with label: ; and then it is likelier to compile.
EDIT: Now that you edited your code all over, it should be JUMP: replaced with JUMP: ; ;-)
#include <stdio.h>
int main() {
int x = 5;
goto JUMP;
printf("x is : %d\n",x);
JUMP:
printf("Do anything after label but dont declare
anything. even empty statement will also work
because label can only be part of a statement");
int a = 0;
printf("%d",a);
}

Mixing C and D code in the same program?

Is it possible? i.e. compile .c with dmc and .d with dmd and then link them together, will this work? Will I be able to call D functions from C code, share globals etc? Thanks.
Yes it is possible. In fact this is one of the main feature of dmd. To call a D function from C, just make that function extern(C), e.g.
// .d
import std.c.stdio;
extern (C) {
shared int x; // Globals without 'shared' are thread-local in D2.
// You don't need shared in D1.
void increaseX() {
++ x;
printf("Called in D code\n"); // for some reason, writeln crashes on Mac OS X.
}
}
// .c
#include <stdio.h>
extern int x;
void increaseX(void);
int main (void) {
printf("x = %d (should be 0)\n", x);
increaseX();
printf("x = %d (should be 1)\n", x);
return 0;
}
See Interfacing to C for more info.
The above answer is wrong as far as I know.
Because the D main routine has to be called before you use any D functions.
This is necessary to "initialize" D, f.e. its garbage collection.
To solve that, you simply can make the program be entered by a main routine in D or you can somehow call the D main routine from C. (But I dont know exactly how this one works)

How to execute some code before entering the main() routine in VC?

I am reading Microsoft's CRT source code, and I can come up with the following code, where the function __initstdio1 will be executed before main() routine.
The question is, how to execute some code before entering the main() routine in VC (not VC++ code)?
#include <stdio.h>
#pragma section(".CRT$XIC",long,read)
int __cdecl __initstdio1(void);
#define _CRTALLOC(x) __declspec(allocate(x))
_CRTALLOC(".CRT$XIC") static pinit = __initstdio1;
int z = 1;
int __cdecl __initstdio1(void) {
z = 10;
return 0;
}
int main(void) {
printf("Some code before main!\n");
printf("z = %d\n", z);
printf("End!\n");
return 0;
}
The output will be:
Some code before main!
z = 10
End!
However, I am not able to understand the code.
I have done some google on .CRT$XIC but no luck is found. Can some expert explain above code segment to me, especially the followings:
What does this line _CRTALLOC(".CRT$XIC") static pinit = __initstdio1; mean? What is the significance of the variable pinit?
During compilation the compiler (cl.exe) throws a warning saying as below:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
stdmacro.c
stdmacro.c(9) : warning C4047: 'initializing' : 'int' differs in levels of indirection from 'int (__
cdecl *)(void)'
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:stdmacro.exe
stdmacro.obj
What is the corrective action needs to be done to remove the warning message?
Thanks in advance.
Added:
I have modified the code and give type to pinit as _PIFV. Now the warning message is gone.
The new code is as follows:
#include <stdio.h>
#pragma section(".CRT$XIC1",long,read)
int __cdecl __initstdio1(void);
typedef int (__cdecl *_PIFV)(void);
#define _CRTALLOC(x) __declspec(allocate(x))
_CRTALLOC(".CRT$XIC1") static _PIFV pinit1 = __initstdio1;
int z = 1;
int __cdecl __initstdio1(void) {
z = 100;
return 0;
}
int main(void) {
printf("Some code before main!\n");
printf("z = %d\n", z);
printf("End!\n");
return 0;
}
A simple way to do this.
#include <iostream>
int before_main()
{
std::cout << "before main" << std::endl;
return 0;
}
static int n = before_main();
void main(int argc, char* argv[])
{
std::cout << "in main" << std::endl;
}
This is what _CRTALLOC is defined as:
extern _CRTALLOC(".CRT$XIA") _PVFV __xi_a[];
extern _CRTALLOC(".CRT$XIZ") _PVFV __xi_z[];// C initializers
extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[];// C++ initializers
It's a table of things to pre-initialise, of which a pointer to your function __initstdio1 is placed.
This page described CRT initialisation:
http://msdn.microsoft.com/en-us/library/bb918180.aspx
In C++ at least, you don't need all that implementation specific stuff:
#include <iostream>
struct A {
A() { std::cout << "before main" << std::endl; }
};
A a;
int main() {
std::cout << "in main" << std::endl;
}
I wrote an award-winning article about this on CodeGuru a while ago.
There's some information here (search for CRT). The significance of variable pinit is none, it's just a piece of data placed in the executable, where the runtime can find it. However, I would advise you to give it a type, like this:
_CRTALLOC(".CRT$XIC") static void (*pinit)()=...
The linker warning probably just warns you you have a function that has int return type, but doesn't return anything (probably you'd better change the return type to void).
Even in C, there is a need for some code to be run before main() is entered, if only to transform the command line into the C calling convention. In practice, the standard library needs some initialization, and the exact needs can vary from compile to compile.
The true program entry point is set at link time, and is usually in a module named something like crt0 for historical reasons. As you've found, the source to that module is available in the crt sources.
To support initializations that are discovered at link time, a special segment is used. Its structure is a list of function pointers of fixed signature, which will be iterated early in crt0 and each function called. This same array (or one very much like it) of function pointers is used in a C++ link to hold pointers to constructors of global objects.
The array is filled in by the linker by allowing every module linked to include data in it, which are all concatenated together to form the segment in the finished executable.
The only significance to the variable pinit is that it is declared (by the _CRTALLOC() macro) to be located in that segment, and is initialized to the address of a function to be called during the C startup.
Obviously, the details of this are extremely platform-specific. For general programming, you are probably better served by wrapping your initialization and your current main inside a new main():
int main(int argc, char **argv) {
early_init();
init_that_modifies_argv(&argc, &argv);
// other pre-main initializations...
return real_main(argc,argv);
}
For special purposes, modifying the crt0 module itself or doing compiler-specific tricks to get additional early initialization functions called can be the best answer. For example, when building embedded systems that run from ROM without an operating system loader, it is common to need to customize the behavior of the crt0 module in order to have a stack at all on which to push the parameters to main(). In that case, there may be no better solution than to modify crt0 to initialize the memory hardware to suit your needs.

Resources