Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Fout:
Adres opschoningsfout: Containeroverloop
Opmerkingen
In Visual Studio 2022 versie 17.2 en hoger is de standaardbibliotheek van Microsoft Visual C++ (STL) gedeeltelijk verlicht voor gebruik met addressSanitizer. De volgende containertypen bevatten aantekeningen om problemen met geheugentoegang te detecteren:
| Standaardcontainertype | Macro aantekeningen uitschakelen | Ondersteund in versie |
|---|---|---|
std::vector |
_DISABLE_VECTOR_ANNOTATION |
Visual Studio 2022 17.2 |
std::string |
_DISABLE_STRING_ANNOTATION |
Visual Studio 2022 17.6 |
Er zijn controles om ervoor te zorgen dat er geen ODR-schendingen (One Definition-Rule) zijn. Een ODR-schending treedt op wanneer een vertaaleenheid een standaardtype aantekent, zoals vector, met ASan-aantekeningen, maar een andere vertaaleenheid niet. In dit voorbeeld ziet de linker mogelijk tegelijkertijd een declaratie met vector<int>::push_back aantekeningen voor adresopschoning en een andere declaratie hiervan vector<int>::push_back niet. Om dit probleem te voorkomen, moeten elke statische bibliotheek en elk object dat wordt gebruikt om het binaire bestand te koppelen, ook ASan-aantekeningen inschakelen. In feite moet u deze statische bibliotheken en objecten bouwen met AddressSanitizer ingeschakeld. Het combineren van code met verschillende instellingen voor aantekeningen veroorzaakt een fout:
my_static.lib(my_code.obj) : error LNK2038: mismatch detected for 'annotate_vector': value '0' doesn't match value '1' in main.obj
Als u deze fout wilt oplossen, schakelt u aantekeningen uit in alle projecten die gebruikmaken van de bijbehorende macro of bouwt u elk project met en /fsanitize=address aantekeningen ingeschakeld. (Aantekeningen zijn standaard ingeschakeld.)
Voorbeeld: Toegang tot gereserveerd geheugen in een std::vector
// Compile with: cl /EHsc /fsanitize=address /Zi
#include <vector>
int main() {
// Create a vector of size 10, but with a capacity of 20.
std::vector<int> v(10);
v.reserve(20);
// In versions prior to 17.2, MSVC ASan does NOT raise an exception here.
// While this is an out-of-bounds write to 'v', MSVC ASan
// ensures the write is within the heap allocation size (20).
// With 17.2 and later, MSVC ASan will raise a 'container-overflow' exception:
// ==18364==ERROR: AddressSanitizer: container-overflow on address 0x1263cb8a0048 at pc 0x7ff6466411ab bp 0x005cf81ef7b0 sp 0x005cf81ef7b8
v[10] = 1;
// Regardless of version, MSVC ASan DOES raise an exception here, as this write
// is out of bounds from the heap allocation.
v[20] = 1;
}
Als u dit voorbeeld wilt bouwen en testen, voert u de volgende opdrachten uit in een visual Studio 2022 versie 17.2 of hoger van de opdrachtpromptvenster voor ontwikkelaars :
cl /EHsc example1.cpp /fsanitize=address /Zi
devenv /debugexe example1.exe
Foutresultaat van gereserveerde geheugentoegang in een std::vector
Aangepaste toewijzingen en overloop van containers
Adres Opschoningscontaineroverloopcontroles ondersteunen niet-toewijsdersstd::allocator . Omdat AddressSanitizer echter niet weet of een aangepaste allocator voldoet aan de vereisten van AddressSanitizer, zoals het uitlijnen van toewijzingen op 8 bytegrenzen, of het niet plaatsen van gegevens tussen het einde van de toewijzing en de volgende 8-bytegrens, kan het niet altijd controleren of de toegangen aan het laatste uiteinde van een toewijzing juist zijn.
AddressSanitizer markeert blokken geheugen in segmenten van 8 bytes. Het kan geen ontoegankelijke bytes plaatsen voordat bytes in één segment toegankelijk zijn. Het is geldig om 8 toegankelijke bytes in een segment te hebben of 4 toegankelijke bytes, gevolgd door 4 niet-toegankelijke bytes. Vier niet-toegankelijke bytes kunnen niet worden gevolgd door 4 toegankelijke bytes.
Als het einde van een toewijzing van een aangepaste allocator niet strikt overeenkomt met het einde van een segment van 8 bytes, moet AddressSanitizer ervan uitgaan dat de allocator de bytes maakt tussen het einde van de toewijzing en het einde van het segment dat beschikbaar is voor de allocator of de gebruiker waarnaar moet worden geschreven. Daarom kunnen de bytes in het laatste segment van 8 bytes niet als ontoegankelijk worden gemarkeerd. In het volgende voorbeeld van een vector toewijzing van geheugen met behulp van een aangepaste allocator verwijst '?' naar niet-geïnitialiseerde gegevens en '-' verwijst naar geheugen dat niet toegankelijk is.
std::vector<uint8_t, MyCustomAlloc<uint8_t>> v;
v.reserve(20);
v.assign({0, 1, 2, 3});
// the buffer of `v` is as follows:
// | v.data()
// | | v.data() + v.size()
// | | | v.data() + v.capacity()
// [ 0 1 2 3 ? ? ? ? ][ ? ? ? ? ? ? ? ? ][ ? ? ? ? - - - - ]
// chunk 1 chunk 2 chunk 3
In het vorige voorbeeld heeft segment 3 4 bytes geheugen waarvan wordt uitgegaan dat ze niet toegankelijk zijn omdat ze vallen tussen het einde van de toewijzing van de 20 bytes die zijn gereserveerd (v.reserve(20)) en het einde van de derde logische groepering van 8 bytes (onthoud dat AddressSanitizer blokken geheugen markeert in segmenten van 8 bytes).
In het ideale voorbeeld markeren we het schaduwgeheugen, dat Address Sanitizer voor elk 8-byteblok geheugen opzij zet om bij te houden welke bytes in dat 8-byteblok geldig zijn en die ongeldig zijn (en waarom), zodanig dat v.data() + [0, v.size()) ze toegankelijk zijn en v.data() + [v.size(), v.capacity()) niet toegankelijk zijn. Let op het gebruik van intervalnotatie hier: '[' betekent inclusief en ')' exclusief van. Als de gebruiker een aangepaste allocator gebruikt, weten we niet of het geheugen daarna v.data() + v.capacity() wel of niet toegankelijk is. We moeten ervan uitgaan dat het zo is. We willen deze bytes liever markeren als ontoegankelijk in het schaduwgeheugen, maar we moeten ze markeren als toegankelijk, zodat het mogelijk blijft om toegang te krijgen tot die bytes na de toewijzing.
std::allocator gebruikt de _Minimum_asan_allocation_alignment statische lidvariabele om te vertellen vector en string dat ze de allocator niet kunnen vertrouwen om gegevens direct na de toewijzing te plaatsen. Dit zorgt ervoor dat de allocator het geheugen niet tussen het einde van de toewijzing en het einde van het segment gebruikt. Zo kan een deel van het segment niet toegankelijk worden gemarkeerd door de Address Sanitizer om overschrijdingen te ondervangen.
Als u wilt dat de implementatie vertrouwt dat uw aangepaste allocator het geheugen verwerkt tussen het einde van de toewijzing en het einde van het segment, zodat dit geheugen kan worden gemarkeerd als ontoegankelijk en overschrijdingen kan ondervangen, ingesteld _Minimum_asan_allocation_alignment op uw werkelijke minimale uitlijning. Als AddressSanitizer correct werkt, moet de uitlijning ten minste 8 zijn.
Zie ook
Overzicht van AddressSanitizer
AddressSanitizer bekende problemen
AddressSanitizer-build- en taalreferenties
naslaginformatie over AddressSanitizer-runtime
addressSanitizer schaduwbytes
AddressSanitizer-cloud of gedistribueerde tests
integratie van AddressSanitizer-foutopsporingsprogramma's
voorbeelden van AddressSanitizer-fouten