VS2019 and _NO_CRT_STDIO_INLINE, how to explain this weirdo? - visual-studio-2019

Please check my short code below.
pwrapper.h
#include <stdio.h>
#include <stdarg.h>
extern"C" int mm_printfA(const char *fmt, ...);
extern"C" int mm_printfW(const wchar_t *fmt, ...);
pwrapper.cpp
#include "pwrapper.h"
int mm_printfA(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int ret = vprintf(fmt, args);
va_end(args);
return ret;
}
int mm_printfW(const wchar_t *fmt, ...)
{
va_list args;
va_start(args, fmt);
int ret = vwprintf(fmt, args);
va_end(args);
return ret;
}
main.cpp
#include "pwrapper.h"
// cl /MT /D _NO_CRT_STDIO_INLINE main.cpp pwrapper.cpp
void main()
{
mm_printfA("What is %d?\n", 123);
}
#if 0
void usedull()
{
vprintf(NULL, NULL);
vwprintf(NULL, NULL);
}
#endif
For some reason, I need to compile it with _NO_CRT_STDIO_INLINE, like this:
cl /MT /D _NO_CRT_STDIO_INLINE main.cpp pwrapper.cpp
But link stage fails saying unresolved external symbol vwprintf and vprintf .
A very weird workaround I find out is: Enable the usedull() function body -- although never be called, and, link through pwrapper.lib, using bb.bat below:
#setlocal EnableDelayedExpansion
#set CFLAGS=/D _NO_CRT_STDIO_INLINE
cl /nologo /c /MT %CFLAGS% pwrapper.cpp
#if errorlevel 1 exit /b 4
lib /nologo /out:pwrapper.lib pwrapper.obj
#if errorlevel 1 exit /b 4
cl /nologo /c /MT main.cpp
#if errorlevel 1 exit /b 4
link /nologo main.obj pwrapper.lib
#if errorlevel 1 exit /b 4
Well, this really works, but why?
This is not a pleasant workaround, because each exe project needs to include a "useless" usedull() function. So, is there any better way?
I really can't tell why this workaround works, an explanation of it is very welcome.
==== Some Clarification ====
There were two main.cpp in my original post. Let me name them separately for later reference in case someone would bother to answer this weird question.
main.0.cpp refers to the one without usedull().
main.1.cpp refers to the one with usedull().
In this question, I use VC++ headers and libs for application(not for kernel), and
I compile main.0.cpp and main.1.cpp without _NO_CRT_STDIO_INLINE.
I always compile pwrapper.cpp with _NO_CRT_STDIO_INLINE.
Whether having pwrapper.obj go through pwrapper.lib produce the same result in this issue.

In short:
compiling pwrapper.cpp with -D _NO_CRT_STDIO_INLINE tells the compiler you are going to provide your own implementation of vprintf and vwprintf at link time, and
compiling main.cpp without -D _NO_CRT_STDIO_INLINE tells the compiler to include implementations of vprintf and vwprintf which are used at link time to satisfy both the references from usedull and mm_printfA/mm_printfW
so, this particular combination works to resolve all undefined symbols at link time. See below for more discussion however.
Discussion
In stdio.h, vprintf (which I'll focus on, but vwprintf is configured in the same way) is defined like so:
_Check_return_opt_
_CRT_STDIO_INLINE int __CRTDECL vprintf(
_In_z_ _Printf_format_string_ char const* const _Format,
va_list _ArgList
)
#if defined _NO_CRT_STDIO_INLINE
;
#else
{
return _vfprintf_l(stdout, _Format, NULL, _ArgList);
}
#endif
Note that
if _NO_CRT_STDIO_INLINE is defined, this becomes a forward declaration
whereas if it is not defined, the full body is included in the compilation of the including translation unit.
Additionally, in corecrt_stdio_config.h whether _NO_CRT_STDIO_INLINE is defined determines the value of _CRT_STDIO_INLINE; if it is defined, _CRT_STDIO_INLINE is defined as empty, otherwise it is defined as __inline.
Putting these together,
if _NO_CRT_STDIO_INLINE is not defined, these functions will be candidates for inline expansion,
otherwise a separate implementation of that function will need to be provided at link time.
Default Compilation (no /O1, /O2, no _NO_CRT_STDIO_INLINE)
The above works with the specific compile and link invocations you are using, as without optimization the compiler will simply include the function body in the compilation of main.1.obj. You can see this using dumpbin; running dumpbin -symbols main.1.obj | find "| vprintf" prints:
01D 00000000 SECT8 notype () External | vprintf
showing that main.1.obj provides vprintf as an externally available symbol.
Checking pwrapper.obj, we get:
00A 00000000 UNDEF notype () External | vprintf
showing that vprintf is undefined in this object file, and will need to be provided at link time.
Optimisation for Inline Expansion
However, if we change the optimisation option for inline expansion, we get different results. Using even the first level of optimisation (-Ob1, included in -O1 and -O2) like so:
cl -c -Ob1 main.1.cpp
causes the compiler to incorporate the body of vprintf directly into usedull, and remove the separate implementation of vprintf, which can be confirmed using dumpbin. So, as you would now expect, attempting to link main.1.obj and pwrapper.obj together will once again give your original error:
pwrapper.obj : error LNK2019: unresolved external symbol vwprintf referenced in function mm_printfW
pwrapper.obj : error LNK2019: unresolved external symbol vprintf referenced in function mm_printfA
main.exe : fatal error LNK1120: 2 unresolved externals
Multiple Implementations?
So, following on from that it is apparent that compiling both files with -D _NO_CRT_STDIO_INLINE will fail as there will be no implementations of the relevant methods. What about if both are compiled without this definition?
If we check the object files, both have defined symbols for vprintf:
01D 00000000 SECT8 notype () External | vprintf
and:
01A 00000000 SECT7 notype () External | vprintf
which under normal circumstances would result in errors due both to multiple definitions of a symbol and violations of the One Definition Rule. However, when performing inline expansion, the compiler and linker have your back. As per 2:
Rather than expand an inline function defined in a header file, the compiler may create it as a callable function in more than one translation unit. The compiler marks the generated function for the linker to prevent one-definition-rule (ODR) violations.

Related

Undefined behavior sanitizer suppression file: failed to parse suppressions

After compiling an application with clang 3.6 using -fsanitize=undefined,
I'm trying to start the instrumented program while using a suppression file to ignore some of the errors:
UBSAN_OPTIONS="suppressions=ubsan.supp" ./app.exe
The suppression file ubsan.supp contains:
signed-integer-overflow:example.c
This leads to an error message:
UndefinedBehaviorSanitizer: failed to parse suppressions
The same occurs with a gcc 4.9 build.
The only documentation I can find is http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html, which is for clang 3.9, while I use 3.6 (which doesn't have documentation for ubsan included).
Can anyone provide working examples for ubsan suppression files, that work in clang 3.6?
Edit: By browsing the source code of ubsan, I found that the only valid suppression type might be "vptr_check" - dunno which version I was looking at though.
Can anyone confirm that in clang 3.9 more suppression types are available?
I didn't spend the time to find out exactly which suppressions were available in clang-3.6, but it appears that in clang-3.7 only vptr_check is available as a suppression. Starting in clang-3.8, the suppressions list is defined to be the list of checks, plus vptr_check.
In clang-3.9 the checks available are:
"undefined"
"null"
"misaligned-pointer-use"
"alignment"
"object-size"
"signed-integer-overflow"
"unsigned-integer-overflow"
"integer-divide-by-zero"
"float-divide-by-zero"
"shift-base"
"shift-exponent"
"bounds"
"unreachable"
"return"
"vla-bound"
"float-cast-overflow"
"bool"
"enum"
"function"
"returns-nonnull-attribute"
"nonnull-attribute"
"vptr"
"cfi"
"vptr_check"
I'd tried it by creating three files, compile.sh, main.cpp and suppressions.supp as shown below. The unsigned-integer-overflow is not a part of undefined that's why it needs to be included specifically. This works on my machine with clang-3.9.
So, I'd guess more suppression types are valid in clang-3.9.
# compile.sh
set -x
UBSAN_OPTIONS=suppressions=suppressions.supp:print_stacktrace=1 #:help=1
export UBSAN_OPTIONS
clang++-3.9 -g -std=c++11 -fsanitize=undefined -fno-omit-frame-pointer -fsanitize=unsigned-integer-overflow main.cpp
./a.out
// main.cpp
#include <bits/stdc++.h>
#include <bits/stl_tree.h>
using namespace std;
int main(int argc, char **argv) {
unsigned int k = UINT_MAX;
k += 1;
return 0;
}
# suppressions.supp
unsigned-integer-overflow:main.cpp

Getting bison parser to divulge debug information

I am having trouble writing a bison parser, and unexpectedly ran into difficulties getting the parser to print debug information. I found two solutions on the web, but neither seems to work.
This advocates to put this code in the main routine:
extern int yydebug;
yydebug = 1;
Unfortunately the C++ compiler detects an undefined reference to `yydebug'.
This suggests putting
#if YYDEBUG == 1
extern yydebug;
yydebug = 1;
#endif
into the grammar file. It compiles but does not produce output.
What does work is to edit the parser file itself, replacing
int yydebug;
by
int yydebug = 1;
The big disadvantage is that I have to redo this every time I change the grammar file, which during debugging would happen constantly. Is there any other way I can provoke the parser into coughing up its secret machinations?
I am using bison v2.4.1 to generate the parser, with the following command-line options:
bison -ldv -p osil -o $(srcdir)/OSParseosil.tab.cpp OSParseosil.y
Although the output is a C++ file, I am using the standard C skeleton.
With bison and the standard C skeleton, to enable debug support you need to do one of the following:
Use the -t (Posix) or --debug (Bison extension) command-line option when you create your grammar. (bison -t ...)
Use the -DYYDEBUG=1 command-line option (gcc or clang, at least) when you compile the generated grammar (gcc -DYYDEBUG=1 parser.tab.c ...`).
Add the %debug directive to your bison source
Put #define YYDEBUG 1 in the prologue in your bison source (the part of the file between %{ and %}.
I'd use -t in the bison command line. It's simple, and since it is Posix standard it probably will also work on other derived parser generators. However, adding %debug to the bison source is also simple; while it is not as portable, it works in bison 2.4.
Once you've done that, simply setting yydebug to a non-zero value is sufficient to produce debug output.
If you want to set yydebug in some translation unit other than the generated parser itself, you need to be aware of the parser prefix you declared in the bison command line. (In the parser itself, yydebug is #defined to the prefixed name.) And you need to declare the debug variable (with the correct prefix) as extern. So in your main, you probably want to use:
extern int osildebug;
// ...
int main(int argc, char** argv) {
osildebug = 1;
// ...
}
If you're using bison, your best place to find information is the bison manual; most of the above answer will be found in that page.

win32-g++ error on for_each and lambda

I know this theme often turns up on stackoverflow, but the case here is different:
The following code compiles with MsVC++ 2013 but not with win32-g++. Is there any way of making it work with both compilers?
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int>my_vector;
for(int i=0; i < 6; i++)
my_vector.push_back(i);
for_each( my_vector.begin(), my_vector.end(), [ ](int n){cout<<n;});
return 0;
}
The errors reported are
||=== stdtest, Debug ===|
D:\dev\CplusPlus\stdtest\main.cpp||In function 'int main()':|
D:\dev\CplusPlus\stdtest\main.cpp|13|warning: lambda expressions only available with -std=c++11 or -std=gnu++11 [enabled by default]|
D:\dev\CplusPlus\stdtest\main.cpp|13|error: no matching function for call to 'for_each(std::vector<int>::iterator, std::vector<int>::iterator, main()::<lambda(int)>)'|
D:\dev\CplusPlus\stdtest\main.cpp|13|note: candidate is:|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\stl_algo.h|4436|note: template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)|
D:\dev\CplusPlus\stdtest\main.cpp|13|error: template argument for 'template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)' uses local type 'main()::<lambda(int)>'|
D:\dev\CplusPlus\stdtest\main.cpp|13|error: trying to instantiate 'template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)'|
||=== Build finished: 3 errors, 1 warnings (0 minutes, 0 seconds) ===|
I should add that I am assuming that the C++11 standard is turned on because "enabled by default". In case I am wrong, I am having a hard time finding out how to change the compiler switches from Code::Blocks.
it turns out that I was misled by the statement that -sdd=C++11 was "enabled by default".
I ended up finding a way of turning it on with the Project > Build Options> compiler settings
and then I clicked on the checkbox "have g++ follow the c++11 ISO C++ language settings" checkbox.
For those who are working with QtCreator add the following line to the project file:
QMAKE_CXXFLAGS += -std=c++11

Flex C++ VTable Error

I am using Flex and Bison to create a compiler. As I am trying to create an AST (Abstract Syntax Tree) for my program, I need to port it to C++. So far I have been successful, until a encountered a rather obscure error from my compiler:
Kraken.o: In function Kraken::FlexScanner::FlexScanner()':
Kraken.cc:(.text._ZN6Kraken11FlexScannerC2Ev[_ZN6Kraken11FlexScannerC5Ev]+0x26): undefined reference to vtable for Kraken::FlexScanner'
Kraken.o: In function Kraken::FlexScanner::~FlexScanner()':
Kraken.cc:(.text._ZN6Kraken11FlexScannerD2Ev[_ZN6Kraken11FlexScannerD5Ev]+0xb): undefined reference to vtable for Kraken::FlexScanner'
Here is all the relevant code:
Kraken.cc:
#include "KrakenScanner.hh"
#include "KrakenParser.hh"
int main(int argc, char * argv[]) {
Kraken::Parser parser;
return parser.parse();
}
KrakenScanner.hh:
#ifndef KRAKENSCANNER_HH_
#define KRAKENSCANNER_HH_
#if ! defined(yyFlexLexerOnce)
#include <FlexLexer.h>
#endif
#undef YY_DECL
#define YY_DECL int Kraken::FlexScanner::yylex()
#include "parser.hh"
namespace Kraken {
class FlexScanner : public yyFlexLexer {
public:
int yylex(Kraken::BisonParser::semantic_type* lval);
private:
int yylex();
Kraken::BisonParser::semantic_type* yylval;
};
}
#endif /* KRAKENSCANNER_HH_ */
KrakenScanner.cc:
#include "KrakenScanner.hh"
int Kraken::FlexScanner::yylex(Kraken::BisonParser::semantic_type* lval) {
yylval = lval; return yylex();
}
Makefile:
OBJS := Kraken.o parser.o scanner.o KrakenScanner.o KrakenParser.o
%.cc: %.y
bison -o $(#:%.o=%.d) $<
%.cc: %.l
flex -o$(#:%.o=%.d) -i $<
all: $(OBJS)
g++ -okraken $(OBJS)
Kraken.o: Kraken.cc KrakenScanner.o KrakenParser.o
KrakenScanner.o: KrakenScanner.hh KrakenScanner.cc parser.o
parser.o: parser.hh parser.cc
parser.cc: parser.y
scanner.o: scanner.cc
scanner.cc: scanner.l
KrakenParser.o: KrakenParser.hh KrakenParser.cc KrakenScanner.o`
I don't know if this will help, but FlexLexer.h defines the classes FlexLexer and yyFlexLexer. FlexLexer declares just a virtual destructor, and yyFlexLexer defines both a constructor and destructor. Also, when I attempt to overload the constr. and destr. in Kraken.cc, I get an error saying that the two are "implicitly defined".
Try a clean rebuild (rm *.o) and recompile. The compiler is supposed to generate this stuff automatically. Some compilers have special non-portable magic to influence v-table linking, but I don't see anything like that in your code.
Also, I see in your makefile that you've written a rule for linking with g++, but you haven't written any rule for compilation. So make is using its built-in rules, which might by the C++ compiler provided by your OS, not g++.
Another thing is that makefile rules should put the primary source first. For example:
wrong:
KrakenScanner.o: KrakenScanner.hh KrakenScanner.cc parser.o
right:
KrakenScanner.o: KrakenScanner.cc KrakenScanner.hh
Finally, object files aren't used to build other object files, only during linking.
First off, that error message is from your linker, not your compiler. It looks like you aren't linking in KrakenScanner.o. It also helps to apply the name demangler for your compiler to your compiler/linker error output.
What compiler are you using?

Cannot link a minimal Lua program

I have the following trivial Lua program which I copied from the book Programming In Lua
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main (void)
{
char buff[256];
int error;
lua_State *L = luaL_newstate(); /* opens Lua */
luaL_openlibs(L); /* opens the standard libraries */
while (fgets(buff, sizeof(buff), stdin) != NULL)
{
error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
lua_pcall(L, 0, 0, 0);
if (error)
{
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
}
}
lua_close(L);
return 0;
}
my environment is cywin
my make file looks like this:
CC=gcc
INCLUDE='-I/home/xyz/c_drive/Program Files/Lua/5.1/include'
LINKFLAGS='-L/home/xyz/c_drive/Program Files/Lua/5.1/lib' -llua51
li.o:li.c
$(CC) $(INCLUDE) -c li.c
main:li.o
$(CC) -o main $(LINKFLAGS) li.o
clean:
rm *.o
rm main
My /home/xyz/c_drive/Program Files/Lua/5.1/lib directory contains lua5.1.dll lua5.1.lib lua51.dll and lua51.lib
Trying to build my main target I am getting the following errors:
li.o:li.c:(.text+0x35): undefined reference to `_luaL_newstate'
li.o:li.c:(.text+0x49): undefined reference to `_luaL_openlibs'
li.o:li.c:(.text+0xaf): undefined reference to `_luaL_loadbuffer'
li.o:li.c:(.text+0xd9): undefined reference to `_lua_pcall'
li.o:li.c:(.text+0x120): undefined reference to `_lua_tolstring'
li.o:li.c:(.text+0x154): undefined reference to `_lua_settop'
li.o:li.c:(.text+0x167): undefined reference to `_lua_close'
Any ideas about what I might be doing wrong here?
The problem is that you have named the libraries on the link command line before the object files that require them. The linker loads modules from left to right on the command line. At the point on the line where you name -llua51, no undefined symbols that could be satisfied by that library are known. Then you name li.o, which does have unknown symbols.
Some Unix-like environments don't treat this as an error because part of the link process is deferred to the program load when reference to .so files are satisfied. But Cygwin, MinGW, and Windows in general must treat this as an error because DLLs work quite differently from .so files.
The solution is to put -llua51 after all the .o files on your link line.
Edit: Incidentally, it appears you are linking against the Lua for Windows distribution, but building with GCC under Cygwin. You will want to use Dependency Walker to make sure that your program does not depend on the Cygwin runtime, and that it does depend on the same C runtime as the lua51.dll from Lua for Windows. IIRC, that will be the runtime for the previous version of Visual Studio. It is possible to make GCC link against that, but you will need to be using the MinGW port (which you can use from Cygwin), and link against a couple of specific libraries to get that version. I'm away from my usual PC, or I'd quote an exact link line. (I believe you need -lmoldname -lmsvcr80 or something like that, as the last items on the link line.)
It will cause mysterious and very hard to diagnose problems if more than one C runtime library is in use. The easy answer is to use the same one as your preferred Lua DLL. Another alternative is that the Lua Binaries project has pre-compiled Lua DLLs for a wide array of C toolchains on Windows. If you need a Lua application that understands the Cygwin environment, you will want one that is built by GCC for Cygwin and not the Lua for Windows flavor. Lua Binaries will be your friend, or you can build Lua your self from source.
The names in the Lua API do not have those leading underscores. Try compiling with -fno-leading-underscore.

Resources