2

I'm working on a program that will monitor the usage of chosen programs and will log it into a .csv file. That way, I can determine what programs use up the most of a certain resource while I run a game in full-screen. I have included the psapi header like so:

...
#include <psapi.h>
...

And I compile with MinGW's G++ with the following options and necessary libraries for the function I'm using (libraries were from the documentation of the function): g++ -lkernel32 -lpsapi test.cpp -o test.exe

Yet it still throws the error:

c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: C:\Users\james\AppData\Local\Temp\cclpYDm2.o:test.cpp:(.text+0x3e7): undefined reference to `GetProcessMemoryInfo@12'
collect2.exe: error: ld returned 1 exit status

I feel that either something is wrong with my library or there's something I'm doing wrong. I've tried surrounding the header with "extern "C"" and I still get the same exact message. I have also verified that the library exists; if it did not, the compiler would have thrown a different error. #pragma comment does not work either, and using the -static flag has no effect. I have also tried defining the PSAPI_VERSION macro and setting it to 1, placing it before the include statement of psapi.

TL;DR: Compiler is throwing an undefined reference error despite having correct libraries. I suspect it's either:

  • Library was installed incorrectly
  • I'm doing something wrong on linking
Zhiyao
  • 4,152
  • 2
  • 12
  • 21
Jamesthe1
  • 107
  • 14
  • To whoever marked this as a duplicate, could you please tell me what answer this relates to? Thanks. – Jamesthe1 Aug 03 '19 at 13:38
  • 1
    Try linking against `kernel32.lib` – Paul Sanders Aug 03 '19 at 13:48
  • Thank you, but unfortunately it still threw the same error, with and without psapi's library included. – Jamesthe1 Aug 03 '19 at 13:53
  • @Jamesthe1 Well, it seems you miss to link the library which contains the implementation for `GetProcessMemoryInfo()` (I guess that's part of the Windows SDK). It's very clear that it was me marking that as a duplicate BTW. – πάντα ῥεῖ Aug 03 '19 at 13:56
  • Upon re-reading the documentation, I **do** have the proper libraries linked. https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getprocessmemoryinfo#requirements – Jamesthe1 Aug 03 '19 at 14:02
  • So, is this a me issue, a linker issue, or a library issue? – Jamesthe1 Aug 03 '19 at 23:36
  • A minimal, complete example that could replicate the problem would have been helpful. It's hard to know if you ever got everything right at the same time. For example, where did you put the `#define PSAPI_VERSION 1`? Maybe it's in the wrong place. – David Schwartz Aug 03 '19 at 23:47
  • The macro was defined before any include. I understand that 'function@num' usually means it has something to do with a library (if it were an incorrectly-declared function, it would print out 'function(arg)' instead) – Jamesthe1 Aug 04 '19 at 00:02
  • 1
    @πάνταῥεῖ Could you please re-open this question? No solution exists within the highly-general post you linked to, and I have described how it is different. – Jamesthe1 Aug 04 '19 at 00:48

1 Answers1

4

Please try this instead. The sequence of arguments you provided to g++ actually matters. Always put the library at the end of your arguments.

g++ -o test.exe test.cpp -lkernel32 -lpsapi

The g++ tool chain will first go through test.cpp and compile it to a binary object file, which is a temporary file having a funny name, but let us call it test.o for now. At this time, there are still some function references in test.o which cannot be resolved.

Then, the g++ tool chain sees -lkernel32 and then -lpsapi. It goes in these two libraries in sequence and find those missing functions in test.o for you.

If you are linking statically, it will copy the compiled binary code of the functions in need from the library and splice it to test.o. If you are linking dynamically, it will set up some "entry" to the dynamic library.

This is what makes the sequence to be important. The compiler tool chain will only copy (set up entry) those function in need, since a library is typically very large and contains many other functions you don't really need. When currently nothing is needed from the libraries, like the command you originally wrote, g++ needs nothing from -lkernel32 -lpsapi before running into test.cpp, it will simply skip those libraries.

In short, if lib_a depends on lib_b, you should put lib_a before lib_b in the arguments. In rare cases where lib_x depends on lib_y which in turn depends on lib_x, you must write something like g++ file.cpp lib_x lib_y lib_x.

Note that this rule only applies to libraries. All functions in the source file will be kept in the binary object file. Thus, even if file_x depends on file_y, writing g++ file_y.cpp file_x.cpp is okay, since all functions are kept in file_y.o and file_x.o, when linking them together, the linker can find them.

Related question: GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'

Zhiyao
  • 4,152
  • 2
  • 12
  • 21