sizeof(void*) is 4 on 64 target - visual-c++

I'm compiling a 64 bit c++ project on visual studio pro 2010 and I'm testing the size of pointers. It shows that sizeof(any pointer) such as void*, char* etc is 4 bytes. This seems wrong for a 64 bit system. However, sizeof(UINT_PTR) is 8 which is correct for 64 bit.
Here's my preprocessor definition: _WIN64;_AMD64;_WINDOWS;_DEBUG;_USRDLL;
Target machine is MachineX64 (/MACHINE:X64).
Is there someplace where the sizeof() of things is defined? Otherwise, how can I find out why it's giving me the wrong size?
Thanks.
Edit:
Compiler command line:
/Zi /nologo /W4 /WX- /Od /D "_WIN64" /D "_AMD64" /D "_WINDOWS" /D "_DEBUG" /D "_USRDLL" /D "_WINDLL" /D "_MBCS" /D "_AFXDLL" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"x64\Debug\S2TalkerDLL.pch" /Fa"x64\Debug\" /Fo"x64\Debug\" /Fd"x64\Debug\vc100.pdb" /Gd /errorReport:queue
Linker command line:
/OUT:"C:\Users\xxx\Documents\Visual Studio 2010\Projects\S2TalkerDLL\x64\Debug\S2TalkerDLL.dll" /INCREMENTAL /NOLOGO /DLL "WINMM.lib" /DEF:".\S2TalkerDLL.def" /MANIFEST /ManifestFile:"x64\Debug\S2TalkerDLL.dll.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"C:\Users\xxx\Documents\Visual Studio 2010\Projects\S2TalkerDLL\x64\Debug\S2TalkerDLL.pdb" /SUBSYSTEM:WINDOWS /PGD:"C:\Users\xxx\Documents\Visual Studio 2010\Projects\S2TalkerDLL\x64\Debug\S2TalkerDLL.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X64 /ERRORREPORT:QUEUE

Hold on a minute, are you getting sizeof() values from Intellisense or from the compiler? That is, have you tried compiling and running something like this:
#include <cstdio>
int main()
{
::printf("%d\n", sizeof(void*));
return 0;
}
I ask because it appears from the screenshots you posted that you're using Intellisense to determine what sizeof() evaluates to.
Intellisense is something completely separate from the compiler. It's just a tool that attempts to parse your (likely incomplete) code for autocompletion purposes. It may or may not be aware of specific compiler/linker settings like /MACHINE:X64, so sizeof(void*) may give incorrect values.
On the other hand, UINT_PTR is defined via #ifdef macros and integral types like unsigned long or unsigned __int64, which in this case Intellisense will be able to give correct sizes.
The compiler and linker are the programs that actually generates the code and thus has the final say on what sizeof() actually evaluates to. You should compile and run the above code snippet and see the actual output. I get 8 under 64-bits and 4 under 32-bits. Intellisense is only a convenience tool and does not have any bearing on the final executable output.
If you don't have immediate access to a 64-bit machine to test the above code, you can instead try compiling this:
template<unsigned long Size> struct TestSize; // #1
template<> struct TestSize<8> {}; // #2
int main()
{
// If sizeof(void*) == 8, then #2 will be used.
// Otherwise, #1 will be used. Since #1 hasn't
// been completely defined, this line will fail
// to compile if sizeof(void*) != 8.
TestSize<sizeof(void*)>();
}
Thanks to template magic (i.e. template specialization), the above snippet should compile only when sizeof(void*) is equal to 8. You don't need to run the resulting executable; the fact that it compiles means that sizeof(void*) == 8.

Related

CMake: Check existence of MSVC compiler flags

Normally, I use check_cxx_compiler_flag to check whether a given flag is recognized by the currently used compiler. However, I have run into issues with MSVC where some default flags are causing the test to fail due to incompatible flags.
MWE:
cmake_minimum_required(VERSION 3.5)
project(MWE)
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_MINSIZEREL "" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "" FORCE)
check_cxx_compiler_flag("/O2" FLAG_USABLE)
if (NOT FLAG_USABLE)
message(FATAL_ERROR "Flag not usable")
endif()
When this is run on Windows in a developer command prompt, the test fails and the error log contains
Run Build Command(s):C:/Program Files/Microsoft Visual Studio/2022/Enterprise/MSBuild/Current/Bin/amd64/MSBuild.exe cmTC_e3d37.vcxproj /p:Configuration=Debug /p:Platform=x64 /p:VisualStudioVersion=17.0 /v:m && MSBuild version 17.3.1+2badb37d1 for .NET Framework
Microsoft (R) C/C++ Optimizing Compiler Version 19.33.31630 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
cl /c /Zi /W1 /WX- /diagnostics:column /O2 /Ob0 /D _MBCS /D FLAG_USABLE /D "CMAKE_INTDIR=\"Debug\"" /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"cmTC_e3d37.dir\Debug\\" /Fd"cmTC_e3d37.dir\Debug\vc143.pdb" /external:W1 /Gd /TP /errorReport:queue "D:\a\cmake-compiler-flags\cmake-compiler-flags\test\build\CMakeFiles\CMakeTmp\src.cxx"
cl : command line error D8016: '/O2' and '/RTC1' command-line options are incompatible
which clearly shows that the flag is recognized, but it just does not play nicely with the /RTC1 flag, which somehow still gets added to the build.
How can I get rid of these default options (or at least all that are not essential for a build to complete), regardless of the used build configuration, so that my test really checks whether the compiler understands the given flag?
I guess your IDE - Visual Studio is adding this compilation flag. Try running Cmake from command line and the problem should be solved. In order to change VS behavior go to Solution -> Properties -> Configuration Properties -> C/C++ -> Code Generation -> Basic Runtime Checks and change the value of this flag to default or disabled.

boost build - specify compiler options when using Visual C++

Update:
Now, I use
using msvc : 14.0 : : <compileflags>/O1 ;
in my project-config.jam. The behavior is what I expect.
But when I replace /O1 to /Ox, the .lib is same as /O2.
/Ox doesn't work correctly!!!
Origin:
I use this command
b2.exe variant=release
but how do I force boost build to use /Ox instead of /O2?
(The default setting for release builds is /O2, but I want /Ox)
P.S., I try
using msvc : 14.0 : : /Ox ;
in my project-config.jam, but it doesn't work.
See the tutorial here.
The section of interest:
<cflags> ... Pass flags to C compiler.
<cxxflags> ... Pass flags to C++ compiler

Compiling C++/CX on the command line

I get the linker error fatal error C1107: could not find assembly 'platform.winmd': please specify the assembly search path using /AI or by setting the LIBPATH environment variable when I try to compile a C++/CX program on the command line.
The error is the same after I followed the instructions on this page: https://msdn.microsoft.com/en-us/library/dn769142.aspx (to summarize: run cl /ZW /EHsc source.cpp from the Developer Command Prompt for VS2015)
I also tried running vcvarsall.bat x86 store from the Developer Command Prompt for VS2015 but I still get the same error (the same error also happens when running vcvarsall.bat x86 store from a plain command prompt).
UPDATE: Apparently this bug has been fixed in VS2015 Update 1, I have not been able to test myself yet though.
As it turns out some command line parameters are missing from the documentation mentioned in the question, here is the full command line required to compile a small program:
cl /ZW
/ZW:nostdlib
/D WINAPI_FAMILY=WINAPI_FAMILY_APP
/D __WRL_NO_DEFAULT_LIB__
/Gm-
/EHsc
/MDd
/FU"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\store\references\platform.winmd"
/FU"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\1.0.0.0\Windows.Foundation.FoundationContract.winmd"
/FU"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\1.0.0.0\Windows.Foundation.UniversalApiContract.winmd"
smurf.cpp
/link /SUBSYSTEM:CONSOLE
Where smurf.cpp contains:
using namespace Platform;
int main(Platform::Array<Platform::String^>^ args)
{
Platform::Details::Console::WriteLine("This is a C++/CX program.");
}
Will successfully print:
C:\Users\Mikael>smurf.exe
This is a C++/CX program.

CMake, VS2012 and Boost 1.54.0: libboost_filesystem-vc110-mt-gd-1_54.lib missing

I built boost 1.54.0 with Visual Studio 2012 x64.
I tried to build a small demo that is using boost filesystem:
#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cout << "Usage: tut1 path\n";
return 1;
}
std::cout << argv[1] << " " << file_size(argv[1]) << '\n';
return 0;
}
CMake is used to setup the corresponding project for VS2012 x64:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.9)
PROJECT(FilesystemTest)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/build/)
# Visual Studio 2010 Pro Standard: /DWIN32 /D_WINDOWS /W3 /Zm1000 /EHsc /GR
SET(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /W4 /Zi /EHsc /GR- /MP /openmp")
SET(CMAKE_DEBUG_POSTFIX "d")
FIND_PACKAGE(Boost COMPONENTS filesystem system REQUIRED)
# Unicode rules!
ADD_DEFINITIONS(-D_UNICODE)
include_directories(${Boost_INCLUDE_DIR})
LINK_DIRECTORIES( ${Boost_LIBRARY_DIRS} )
file(GLOB FilesystemTest_SOURCES src/*.*)
# Create a target for the library
ADD_EXECUTABLE(FilesystemTest
${FilesystemTest_SOURCES})
But when compiling I get 'libboost_filesystem-vc110-mt-gd-1_54.lib' is missing.
Perviously I used boost 1.53.0 - everything was working perfect when using boost 1.53.0.
When looking into the boost 1.54 lib folder there is only a 'boost_filesystem-vc110-mt-gd-1_54.lib' and a 'libboost_filesystem-vc110-mt-sgd-1_54.lib'
I compiled boost using this instructions:
Download boost 1.54.0 from http://www.boost.org/
Extract files (e.g. “C:\thirdparty\vs2013\x64\boost_1_54_0”)
Start Visual Studio 2012 x64 command prompt
Change to boost directory (e.g. “cd C:\thirdparty\vs2010\x64\boost_1_54_0”)
Execute .\bootstrap.bat
Execute b2 address-model=64 toolset=msvc-11.0 --build-type=complete stage
If only certain libraries (for instance filesystem) are need step 6 can be replaced by this:
b2 address-model=64 toolset=msvc-11.0 --build-type=complete stage --with-filesystem --with-signals --with-system
I could not figure out what is working wrong. Any ideas?
Update
Yesterday I tried again: I used the same commands and I finally got a 'libboost_filesystem-vc110-mt-gd-1_54.lib' file. No idea why it is working now. I installed a few VS2012 updates and also removed my VS2013 Preview installation. But I have no clue why it is working now.
Yesterday I tried again: I used the same commands and I finally got a 'libboost_filesystem-vc110-mt-gd-1_54.lib' file. No idea why it is working now. I installed a few VS2012 updates and also removed my VS2013 Preview installation. But I have no clue why it is working now.

LTCG doesn't remember that /O2 was specified at compile time

Background
I am using CL and LINK from the command line to build a project composed of native C++, mixed C++/CLI, and safe C++/CLI. I need to target .NET Framework 2.0-3.5 so I am using the VC90 toolchain (I have VS2010 but installed VS2008 C++ express and the SDK for Windows 7 and .NET 3.5 SP1 to get the complete VC90 toolchain).
If I try my script with the VS100 toolchain it works fine but targets .NET v4.0. If I don't use /GL for my native and mixed code it works. I know of these solutions, so don't suggest them. I am trying to understand why this is occurring.
Problem
If I use /GL and /LTCG I get many of the following warnings in the native code:
xxx.cpp(###) : warning C4748: /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function
And the following error in the mixed code:
c:\program files (x86)\microsoft visual studio 9.0\vc\include\vcclr.h(47) : error C4801: Return by reference is not verifiable: definition of returned local not found in basic block
The second one is for PtrToStringChars from a Microsoft header file that allows you to use a String^ as const wchar_t* and is a function that MUST be inlined (and is marked inline). The "return by reference" won't actually be a return when inlined, thus no error.
The issue is that I do use optimizations while compiling! I use the standard /O2 which has the highest level of inlining (/Ob2) and normally allows /GS.
Script
Here is my abridged compilation script
set TARGET=x86
call "%VS90COMNTOOLS%\..\..\VC\vcvarsall.bat" %TARGET%
set CL=/nologo /Zl /Zi /W4 /O2 /Oy- /GL /GS /EHa /MP /D NDEBUG /D _UNICODE /D UNICODE /D INTEGRATED /Fdout\ /Foout\
set LINK=/nologo /LTCG /CLRIMAGETYPE:IJW /MACHINE:%TARGET% /SUBSYSTEM:WINDOWS,6.0 /OPT:REF /OPT:ICF /DEFAULTLIB:msvcrt.lib /DEFAULTLIB:msvcmrt.lib
set CSC=/nologo /w:4 /d:INTEGRATED /o+ /target:module
set CL_NATIVE=/c /FI"stdafx-native.h"
set CL_MIXED=/c /clr /LN /FI"stdafx-mixed.h"
set CL_PURE=/c /clr:safe /LN /GL /FI"stdafx-pure.h"
set NATIVE=a.cpp b.cpp ...
set MIXED=c.cpp d.cpp ...
set PURE=e.cpp f.cpp ...
cl %CL_NATIVE% %NATIVE%
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
cl %CL_MIXED% %MIXED%
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
cl %CL_PURE% %PURE%
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
link /LTCG /NOASSEMBLY /DLL /OUT:"out\x.netmodule" out\*.obj
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
Short Version: Inlining in MSIL takes place during JIT, after the code verifier performs accessibility checking.
Long Version:
Whole-Program Optimization doesn't apply to MSIL, because MSIL always gets optimized across compile units, and even across assemblies (unless optimizations are turned off by debug). I think this is the source of your warnings.
Many optimizations are the responsibility of the JIT, including inlining. Coupled with accessibility checks, this prevents the C++ compiler from running an inlining pass on MSIL. (What happens if a member function using private members get inlined in native C++? Not much. What happens if a member function using private members gets inlined in MSIL into a function that has no access to those private members? The .NET runtime throws an absolute fit. Everything you think you know about compiler settings for inlining just doesn't apply to MSIL.) This is why...
...use of PtrToStringChars is incompatible with /clr:safe because it isn't verifiable. It should be fine with /clr though, and also with /clr:pure since neither of those try to create verifiable assemblies. As mentioned, the compiler is not allowed to inline when compiling in /clr modes. This is the source of your error.
A final problem is creation of a netmodule. I'm pretty sure that mixed-mode code has to be created as full-blown assemblies and not netmodules.

Resources