0

Initial problem:
I have a bug caused by an old debug MSVCRT library.
It throws an exception in debug mode for std::string initialization:

std::string str{vecBuff.cbegin(), vecBuff.cend()};

The old debug runtime library detects that std::vector<char>::cend() points to an invalid address and causes an error about HEAP Courruption. It only happens within a MSI Custom Action invocation (and there's an old runtime version which I can do nothing about).

In the comments to this answer there is a solution to set _ITERATOR_DEBUG_LEVEL 1.
I don't want to do that for the whole library. Unfortunatelly, I can't manage to do it for the single .cpp either.
This .cpp uses a precompiled header and disabling it for a single file in the properties changes nothing. I still get an error about stdafx.h missing.

// stdafx.h
#pragma once

#include <string>
// the .cpp file

// Can't include before. Get a lot of warnings.
#include "stdafx.h"

// will not have any effect since <string> is already included in "stdafx.h"
#if _MSC_VER && \
    !__INTEL_COMPILER && \
    _DEBUG
#define _ITERATOR_DEBUG_LEVEL 1
#endif
#include <string>

Though I am initially trying to solve the std::string initialization problem, I'd like to know the answer to a more generic topic, since there are some other places where I might require to customize preprocessof definitions AND use a precompiled header.

Sergey Kolesnik
  • 3,009
  • 1
  • 8
  • 28
  • Youre using Visual Studio? I tried the inverse, im in a test project and i dont use precomp, but i went on the file itself and in the options enabled it and I got a compilation error. Perhaps you can use that (i.e.e turn it off for that file), you would include your precomp anyway but now it should all you to add the define before it? – Borgleader Dec 30 '21 at 23:08
  • @Borgleader if I disable pch for the file, but leave it, and put the preprocessor definitions before `stdafx.h`, I get the same result as with pch enabled. – Sergey Kolesnik Dec 30 '21 at 23:11
  • 1
    Why are you using `begin` with the `cend`? – Dmitry Kuzminov Dec 31 '21 at 00:15
  • I second Dmitry's question. Also, can you edit the code? If so, why not just change it to use the string constructor that takes a `const char*` and a # of characters. That is: `std::string str(&(*(vecBuff.begin()), vecBuff.size());` You might need to add a check for an empty string, of course... – Joe Dec 31 '21 at 02:56
  • @DmitryKuzminov I'm not. It is a typo. – Sergey Kolesnik Dec 31 '21 at 06:23
  • @Joe I don't want to change a perfectly valid modern C++ code to workaround a VC120 runtime in a legacy project. Sadly, I *have to* for now. The question was about changing preprocessor definitions with PCH. I feel like the answer would be "you can't because of UB caused by inconsistency of `_ITERATOR_DEBUG_LEVEL` within the dll". And that would be a fine answer given a proper explanation. – Sergey Kolesnik Dec 31 '21 at 06:33
  • You cannot normally have `_ITERATOR_DEBUG_LEVEL` set to different values in different source files in the same program. – n. m. could be an AI Dec 31 '21 at 09:02
  • @n.1.8e9-where's-my-sharem. that I have figured (see my comment above). You can post it as an answer with additional details about what and why could go wrong – Sergey Kolesnik Dec 31 '21 at 09:05

1 Answers1

2

Defining _ITERATOR_DEBUG_LEVEL to either 1 or 2 changes the representation of iterators. Instead of being lightweight wrappers for e.g. plain pointers into container data, iterators compiled with this option contain a pointer into the data and a pointer to a container proxy object, which contains more info about the container. Thus a program where some object are compiled with _ITERATOR_DEBUG_LEVEL set to 0 and others with _ITERATOR_DEBUG_LEVEL set to something else contains two incompatible versions of each iterator type. This is not a good idea. The compiler therefore tries to detect a mix of different debug levels and introduce a deliberate linker error if a mismatch is found. Even if you manage to inhibit this check somehow, passing iterators between functions compiled with different _ITERATOR_DEBUG_LEVEL value is usually fatal.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243