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.

8
  • 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? Commented Dec 30, 2021 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. Commented Dec 30, 2021 at 23:11
  • 1
    Why are you using begin with the cend? Commented Dec 31, 2021 at 0: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... Commented Dec 31, 2021 at 2:56
  • @DmitryKuzminov I'm not. It is a typo. Commented Dec 31, 2021 at 6:23

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.