STL-std::string-Klasse verursacht Abstürze und Speicherbeschädigung auf Multi-Prozessor-Computern

Artikel-ID: 813810 - Produkte anzeigen, auf die sich dieser Artikel bezieht
Alles erweitern | Alles schließen

Auf dieser Seite

Problembeschreibung

Speicher kann bei dem Erstellen von Anwendungen von Microsoft Visual C++ 6.0, die das angegebene Standard Template Library (STL) verwenden, beschädigt werden oder der Computer reagiert möglicherweise nicht mehr der Ihre. Diese Symptome treten häufiger auf Multi-Prozessor-Computern auf. Derselbe Code funktioniert möglicherweise auf einem Einzel-Prozessor-Computer zuvor ohne solche Probleme. Wenn Sie das Fehler Threads in einem Debugger so untersuchen, finden Sie normalerweise unter dem Fehler in einer Speicherverwaltungsfunktion. Unter den Klassenmethoden basic string<char... > in dem Stack-Trace finden Sie häufig. Da Speicherbeschädigung auch ein Symptom ist, werden Fehler möglicherweise in Bereichen angezeigt, die unabhängig zu der Verarbeitung von Zeichenfolge sind.

Wo dieses Problem einen Absturz verursachte, ist beispielsweise folgender Stack-Trace:
01 0012ebc4 77fb4014 0246ffd0 00000027 02531000 ntdll!RtlpDphReportCorruptedBlock+0x8c
02 0012ebec 77fb2cb1 02531000 01001002 0246ffd0 ntdll!RtlpDphNormalHeapFree+0x46
03 0012ec10 77fb5653 02530000 01001002 0246ffd0 ntdll!RtlpDebugPageHeapFree+0xa6
04 0012ec88 77fa760a 02530000 01001002 0246ffd0 ntdll!RtlDebugFreeHeap+0x203
05 0012ed28 77fcba9e 02530000 01001002 0246ffd0 ntdll!RtlFreeHeapSlowly+0x4d
06 0012edcc 004065a6 02530000 00000000 0246ffd0 ntdll!RtlFreeHeap+0x53
07 0012ee14 0041353a 0246ffd0 00404198 0246ffd0 main!free+0xda
08 0012ee1c 00404198 0246ffd0 0012eecc 004e9b70 main!operator delete+0x9 (FPO: [1,0,0]) (CONV: cdecl) [afxmem.cpp @ 349]
09 0012ee38 00402a71 02477fe0 00000011 004e9ce0 main!basic_string<char,char_traits_char,allocator<char> >::append_helper+0x68 (FPO: [EBP 0x0012eecc] [2,1,4]) (CONV: thiscall)
...
NTDLL! 77f97710()
NTDLL! 77fb5721()
NTDLL! 77fa760a()
NTDLL! 77fcba9e()
MSVCRT! 78001d92()
operator delete(void * 0x00c266f8) line 6 + 10 bytes
std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(std::basic_string<char,std::char_traits<char>,std::allocator<char> > * const 0x0000000f {???}, unsigned char 1) line 591 + 6 bytes
...
00 0184fb9c 60f3abc3 main!__sbh_free_block+0x173
01 0184fbb4 60f2aa93 main!free+0x28
02 0184fbbc 60f2423c main!operator delete+0x9
03 0184fce8 60f244b0 main!function(std::basic_string<char,std::char_traits<char>,std::allocator<char> > var = std::basic_string<char,std::char_traits<char>,std::allocator<char> >)+0x79c
...
...
5ed 0198de20 77fac5f4 0198dec0 0198e3f8 0198dedc ntdll!ExecuteHandler+0x26
5ee 0198dea8 77f91a96 0198dec0 0198dedc 0198dec0 ntdll!RtlDispatchException+0x76
5ef 0198df14 77b22546 2cb01468 47ac0008 00000008 ntdll!KiUserExceptionDispatcher+0xe
5f0 0198e340 1001b22c 00ed0000 00000000 00000080 ole32!SyncStubInvoke+0x61
5f1 0198e37c 1001b123 00000080 1001a4ef 00000080 main!_heap_alloc+0xed
5f2 0198e384 1001a4ef 00000080 00000001 100022f1 main!_nh_malloc+0x10 (FPO: [2,0,0])
5f3 0198e390 100022f1 00000080 0000007c 0198f430 main!operator new+0xb (FPO: [1,0,0])
5f4 0198e3b0 10002207 0000003c 0000007d 0198f42c main!std::basic_stringbuf<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >::overflow+0x83 (CONV: thiscall) [C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE\sstream @ 60]
5f5 0198e3cc 10003194 00000000 0000006b 0198f6e0 main!std::basic_streambuf<unsigned short,std::char_traits<unsigned short> >::xsputn+0x6a (CONV: thiscall) [C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE\streambuf @ 166]
5f6 0198e404 10005621 0198f42c 010113b2 1003573c main!std::operator<<+0xb0 (CONV: cdecl) [C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE\ostream @ 305]
...

Ursache

Das Standard Template Library (STL), das zu Microsoft Visual C++ 6.0 gehört, ist für Anwendungen von Multithreaded nicht sicher. Die Implementierungen der std::string Klasse hängen insbesondere von der Vorlageklasse basic string&lt;...&gt; ab. Der basic string&lt;...&gt; Vorlageklassenverweis zählt Kopien eines ausgeblendeten Zeichenpuffers. Die basic string&lt;...&gt; Vorlageklasse speichert die Anzahl in einem nicht signierten 8-Bitchar. Nach dieser Implementierung treten die folgenden allgemeinen Probleme auf:
  • Die basic string&lt;...&gt; Vorlageklasse schützt den zählenden Mechanismus auf der Synchronisierung, die zu dem Ausführen von Thread auf Multi-Prozessor-Computern zu der gleichen Zeit erforderlich ist, nicht. Multithreaded-STL-Code, der auf Einzel-Prozessor-Computern ausgeführt wird, vermeidet dieses Problem, da zu einer Zeit und Speicher lesen nur ein Thread ausgeführt wird oder Schreiben auf Ganzzahlen abgeschlossen wird, bevor ein anderes Thread unterbrochen werden kann.
  • Klasse in einem Threads kann das Lesen einer Kopie der std::string Klasse, wie einem, der von Zuordnung in einem anderen Thread erstellt wird, beschädigen, in einem std::string zu schreiben. Die angenommene Kopie nutzt den gleichen ausgeblendeten Zeichenpuffer gemeinsam.
  • Zeichenfolge kann beschädigt werden, wo ein Zeiger oder ein Verweis auf einer Klasse std::string zwischen Threads gemeinsam genutzt werden. Es ist in der Regel die Aufgabe des Programmierers, diese Situation zu vermeiden.

Lösung

Nachdem Sie threadsicher das STL durchführen, müssen Sie die Anwendung neu erstellen. Das Aktualisieren des STL auf einer neueren Version, die Standard auf dem aktuellen Visual C++ basiert, ist die ein threadsicheren STL erhaltende bevorzugte Methode. Das STL, das auf dem aktuellen Visual C++-Standard basiert, ist jedoch nicht identisch mit dem STL, das verfügbar zu dem Zeitpunkt der Veröffentlichung von Microsoft Visual 6.0 C++ als ein neues Produkt war. Das Aktualisieren auf einer neuen Version kann jedoch einfach je nach den STL-Funktionen, die Ihre Anwendung verwendet sein. Verwenden Sie eine der folgenden Methoden, um neue Versionen von dem threadsicheren STL zu erhalten:

Methode 1: Microsoft Visual Basic Anwendung Visual C++ (7.0 und höhere Versionen)

Öffnen Sie jedes Visual C++-Projekt in Ihrer Anwendung, lassen zu, um das Projekt automatisch in dem neuen Projektformat zu konvertieren, und erstellen Sie dann es neu. Die std::string Klassenimplementierung in dieser Version ist threadsicher für das beschriebene Problem. Wenn Sie in beliebigem diesem der Projekte der Ihrem die DLL-Funktion der Laufzeitbibliothek in Ihrer Anwendung verwenden, müssen Sie die neuen Visual C++-Laufzeitkomponenten (wie Msvci7x.dll, Msvcp7x.dll und Msvcr7x.dll) mit Ihrer neu erstellten Anwendung verteilen.

Hinweis: Sie müssen das Microsoft .NET Framework auf Clientcomputer nicht anordnen, um Microsoft Visual C++ zu verwenden.

Methode 2: ANWENDUNG-MICROSOFT VISUAL BASIC-C++ 6.0 mit einem Ersatz STL von dritten Party

Die Details der Integration hängen nach Produkt ab und die einzelnen Kreditoren bieten Unterstützung. Eine Quelle für eine Nachfolger-STL-Version ist Dinkumware , Ltd. das Unternehmen das Microsoft das Visual C++ 6.0 STL lizenziert. Dass es in vorhandenen Erstellungsprozessen integriert werden kann, wird beansprucht. Besuchen Sie die folgende Dinkumware Web Website für Weitere Informationen und eine Übersicht über bekannt Probleme und bekannt Problemumgehungen:
www.dinkumware.com
Die Kontaktinformationen bezüglich der in diesem Artikel erwähnten Fremdanbieter sollen Ihnen helfen, den benötigten technischen Support zu finden Diese Kontaktinformationen können ohne vorherige Ankündigung geändert werden Dafür garantiert Microsoft nicht die Genauigkeit dieser Kontaktinformationen von Dritt-Anbieter. Die in diesem Artikel erwähnten Fremdanbieterprodukte werden von einem Lieferanten hergestellt, der von Microsoft unabhängig ist Microsoft gewährt keine implizite oder sonstige Garantie in Bezug auf die Leistung oder Zuverlässigkeit dieser Produkte

Abhilfe

Umgehung des std::string-Klassenproblem in Microsoft Visual C++ 6.0 STL

Wenn Sie nicht auf einer neuen Version von dem STL aktualisieren, können Sie versuchen, das std::string Klasse-Threadsicherheit-Problem in der Microsoft Visual C++ 6.0-Standardinstallation zu beheben. Die sehr allgemeine und problematische Klasse ist by far std::string die Klasse, obwohl es multi-threading Probleme mit mehreren Klassen in dem Microsoft Visual C++ 6.0 STL geben. Die folgenden Schritte und die folgenden Problemumgehungen sind Stopgap-Measure, sicherzustellen, dass eine Anwendung richtig funktioniert, und die Measures Zeit für das Untersuchen weiterer Alternativen Zeit bieten. Berücksichtigen Sie, dass diese Anweisungen neue Codepfade und Verhalten vielleicht in Ihrer gesamten Anwendung erstellen werden. Gründlich testen die neu erstellte Anwendung entsprechend einem Unternehmen oder einer Person Sie Softwarerichtlinien vor umfangreicher Bereitstellung.

Deaktivieren Sie einen Referenz-Zeichenfolge-Zähler

Die einzelnen Problemumgehungen, die in diesem Abschnitt dokumentiert sind, erfordern, dass Sie den Reference-count-Mechanismus zuerst deaktivieren. Um einen Referenzzähler zu deaktivieren, müssen Sie die &lt;xstring&gt; Headerdatei ändern und Sie müssen die FROZEN Aufzählungskonstante auf 0 festlegen. Die Headerdatei <Xstring> ist Standard Installationen an dem folgenden Speicherort:
C:\Program Files\Microsoft Visual Studio\VC98\Include
Ändern Sie die FROZEN Aufzählungskonstante in 0 in der Headerdatei &lt;xstring&gt; in Zeile 62, damit es folgend ähnelt:
enum _Mref {_FROZEN = 0}; // set to zero to disable sharing; original value 255
Wenn Sie dieser Empfehlung folgen und wenn gesamte Software neu erstellen, die diese Headerdateien verwendet, wird Ihr std::string Klassencode threadsicher sein. Es gibt einige Einschränkungen an der Anweisung. Durchlesen Sie die folgenden Anweisungen von Problemumgehung sorgfältig daher. Wenden Sie eine der folgenden Methoden an, um dieses Problem umzugehen, nachdem Sie Verweis deaktivieren, der der zählt, indem die FROZEN Aufzählungskonstante auf 0 in der Headerdatei &lt;xstring&gt; festlegt.

Methode 1: verwenden Sie nur statische CRT-Bindung

Ändern Sie die Einstellungen von Projekt in allen Projekten Ihren, die die die std::string Klasse verwenden, um auf der statischen Version der Microsoft-Laufzeitbibliothek (CRT) zu verknüpfen. Wenn Ihr Projekt außerdem verfügt über aktiviert von der Einstellung von Use MFC in a Shared DLL sein, können Sie diese Methode nicht verwenden. Gehen Sie für jedes Projekt folgendermaßen vor:
  1. Öffnen Sie das Projekt.
  2. Klicken Sie in dem Menü Projekt auf Einstellung.
  3. Klicken Sie in der Liste Configurations auf Release.
  4. Klicken Sie auf die Registerkarte C/C++, und klicken Sie dann in der Liste Kategorie auf Codeerstellung.
  5. Auf <UITERM> klickt Sie in der Liste Runtime library Multi-thread (/ MT )</UITERM>.
  6. Klicken Sie in der Liste Configurations auf Debuggen.
  7. Auf Multi-thread <UITERM>-debug klickt Sie in der Liste Runtime library (/ MTd )</UITERM>.
  8. Wenn andere Konfigurationen in der Liste Configurations sind, legte Sie das entsprechende Runtime library fest Option außerdem für sie.
  9. Klicken Sie auf OK, und erstellen Sie dann das Projekt neu.
Diese Problemumgehung stellt sicher, dass Ihr gesamter Code die geänderte Version der &lt;xstring&gt; Datei für das statische Verknüpfen zu der Laufzeitbibliothek ganz Multithreaded verwendet, die MFC enthält. Ein mögliches Problem ist, dass letzter Code der Ihre größer als eine dynamisch verknüpfte Version sein wird, vielleicht enormously ja.

Methode 2: verwenden Sie dynamische CRT-Bindung

Wenn zu der Laufzeitbibliothek (CRT) als ein DLL Ihr Projektcode verknüpft werden muss, müssen Sie eine andere Vorgehensweise annehmen. Standardeinstellung für DLL-Projekte lautet dynamischer CRT-Bindung. Abhängigkeiten von anderen Komponenten, wie MFC oder Bibliotheken von Dritt-Anbieter, die für Verwendung Ihrer Anwendung lizenziert sind, erfordern dynamische Bindung zu dem CRT normalerweise. Wenn MFC Ihre einzige Abhängigkeit ist können Sie die MFC in einer statischen Bibliothek verwenden Option verwenden und Sie können Methode 1 anwenden. Wenn Sie ein neues Projekt in Microsoft Visual C++ 6.0 erstellen, verwendet das Projekt das CRT aus einem DLL standardmäßig.

Die CRT-Bindungsprojekteinstellung von dynamische verknüpft Ihre Anwendung an Implementierungen für std::string einige Klassenmethoden in dem bereits erstellten Microsoft CRT DLL, das als Msvcp60.dll bezeichnet wird. Für Funktionen, die aus der Bibliothek aufgerufen werden, wird die Änderung an der Konstante FROZEN, die Sie an die lokale Kopie von &lt;xstring&gt; vornahmen, nicht beachtet, da Microsoft das DLL erstellte, indem Microsoft die unveränderte &lt;xstring&gt; Headerdatei verwendet. Die fügt Funktionen wie Tidy() und Assign() ein, die zu der Verfügung in der Msvcp60.dll-Datei für die &lt;char&gt;- der basic string Klasse und die &lt;short&gt;-Instanziierung der basic string Klasse gestellt werden. Die basic string Klasse ist die Basis für die Klasse std::string.

Gehen Sie folgendermaßen vor, um statische Implementierungen der std::string Klasse in Ihren Unterrichtseinheiten statt der Implementierungen von Microsoft-supplied in der Msvcp60.dll-Datei zu verwenden:
  1. Auskommentieren Sie in der Datei <Xstring> den folgenden Code, der gegen dem Ende der Datei gefunden wird. Zu Zweck können Sie den Code in einem Block #if 0/#endif einschließen:
    #ifdef _DLL
    #pragma warning(disable:4231) /* the extern before template is a non-standard extension */
    extern template class _CRTIMP basic_string<char, char_traits<char>, allocator<char> >;
    extern template class _CRTIMP basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >;
    #pragma warning(default:4231) /* restore previous warning */
    #endif  // _DLL
  2. Andere Zeichenfolge-Operatoren sind in der Headerdatei <Zeichenfolge> definiert, und ebenfalls sind in dem CRT sie über die Msvcp60.dll-Datei enthalten. An dem Ende der Datei <Zeichenfolge> dass "Reihe ... der _CRTIMP Vorlage Extern" stammt, beachten Sie Definitionen, die nur wie durch die Klausel #ifdef DLL in der Datei <Xstring> geschützt sind. Kommentieren Sie alle Definitionen out außerdem:
    #ifdef _DLL
     #pragma warning(disable:4231) /* the extern before template is a non-standard extension */
     
    extern template class _CRTIMP
        basic_string<char, char_traits<char>, allocator<char> > __cdecl operator+(
            const basic_string<char, char_traits<char>, allocator<char> >&,
            const basic_string<char, char_traits<char>, allocator<char> >&);
    extern template class _CRTIMP
        basic_string<char, char_traits<char>, allocator<char> > __cdecl operator+(
    ...
    extern template class _CRTIMP
        basic_ostream<wchar_t, char_traits<wchar_t> >& __cdecl operator<<(
            basic_ostream<wchar_t, char_traits<wchar_t> >&,
            const basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >&);
    
    #pragma warning(default:4231) /* restore previous warning */
    #endif      // _DLL
  3. Speichern Sie die Änderungen an diesen Dateien und erstellen Sie dann alle Projekte in der Anwendung, die das STL verwenden, neu. Wenn Ihr Projekt ein Klasse class declspec(dllexport) deklariert und wenn die Klasse über Member des std::string Typen verfügt, sehen Sie C4251-Warnungen. Sie können Warnung ignorieren, da Ihr gesamter Code mit der Klasse std::string erstellt wird, die jetzt statisch verknüpft wird. Verwenden Sie die folgende Notation, um Warnung explizit zu deaktivieren:
    #pragma warning(disable: 4251)
Dieser Ansatz verteilt die Verwendung von MFC- anders als der Klasse std::string von DLLs und CRT-Funktionen anders als der Klasse std::string von DLLs. Eine kleine Steigerung von Codeumfang in jeden Modulen Ihren, die die std::string Klasse verwenden, ist.

Methode 3: Verwenden eines intelligenten Hacks, um Bindungsprobleme zu vermeiden

Erstellen Sie ein Typedef für unsigned char und verwenden Sie das std::string statt des vorhandenen Klassentypedef. Das Typedef kann ein Formular, das enthalten wird, in einer Headerdatei in den Quelldateien der Anwendung, für die die std::string Klasse verwendet, dauern. Scheint das Typedef wie folgend vergleichbar:
typedef std::basic_string<unsigned char> MyString;
#define string MyString
Beliebige Zeichenfolgenliterale, die für diese Klasse verwandt werden, müssen umwandelt werden oder als nicht signiertes Char aufbereitet werden. Eine Steigerung von Codeumfang versus Freundlichkeit der Implementierung befindet sich möglicherweise und weniger Bindungsnebeneffekte sind.

Methode: 4: Verwenden eines benutzerdefinierten std::string DLL

Diese Option erhält Ihnen den Vorteil der kleinsten Codegröße, indem diese Option die Klassenimplementierungen std::string in einem einzelnen DLL versetzt. Erstellen Sie ein DLL-Projekt, das die std::string Klasse exportiert. Verknüpfen Sie mit dem DLL zu der Standard-Msvcp60.dll-Datei. Zusammmen mit Ihrer Anwendung müssen Sie dieses neue DLL weiterverteilen. Das ist eine erweiterte Option.

Weitere Informationen

Szenario, das auftreten kann, wenn ein Fehlen der Synchronisierung ist, wird in den folgenden C++-Codebeispielen veranschaulicht:
...
std::string	A;
A = "Init";
_beginthread(Thread1, 0, (void*)&A);
_beginthread(Thread2, 0, (void*)&A);
A = "";
...

void Thread1(void* arg)
{
	std::string	A1 = *(std::string*)arg;
	...
	A1 = "newval";
}

void Thread2(void* arg)
{
	std::string	A2 = *(std::string*)arg;
	...
	std::string	B = A2;
	A2 = "newval2";
}
In diesem Beispiel kopiert Thread1 das Eingabeargument und Thread1 löst den freigegebenen Verweis-Pufferzeichenzähler auf 1 aus. Thread2 kopiert sein Eingabeargument und löst den Verweis-Zähler auf 2 außerdem aus, während es arbeitet. Zu A weist das Hauptthread in Zwischenzeit einen neuen Wert zu, das Hauptthread erstellt einen neuen Zeichenpuffer und das Hauptthread löscht den Verweis-Zähler in dem freigegebenen ursprünglichen Puffer auf 1.

Thread1 startet, einen neuen Zeichenpuffer für die neue Zuordnung auf A1 zu erstellen, erkennt einen positiven Verweis-Zähler in seinem freigegebenen vorherigen Zeichenpuffer und dann in seinen Dekrementen, die von 1 zu 0 zählen. Im Verlauf von Zuordnung zu B B ist Thread2 auch der Freigaben Zeichenpuffer von A2 zu der gleichen Zeit und Thread2 löst den Verweis-Pufferzeichenzähler von A2 aus, zu versuchen es auf 2 zu erhöhen, bevor Thread1 ein 0 nur in dem Verweis-Zähler schreibt. Der Verweis-Zähler ist jetzt 0 statt 1. Der Verweis-Zähler hat 0 gewesen, wenn Zugriff auf den Verweis-Zähler synchronisiert wurde.

Wenn Thread2 zu A2 einen neuen Wert zuweist sieht Thread2 den Verweis-Zähler 0 und Thread2 verwirft den freigegebenen ursprünglichen Zeichenpuffer, auf den B weiterhin verweist. Der Arbeitsspeicher, der den Zeichenpuffer enthielt, ist jetzt für andere Verwendungen in der Anwendung verfügbar. Std::string B bewegt jedoch einen Zeiger weiterhin an dem Zeichenpuffer. Die folgenden Szenarios verursachen Beschädigung und Abstürze:
  • B versucht, den Zeichenpuffer freizugeben.
  • B versucht, die Inhalte des Zeichenpuffers zu lesen, die mit Livedaten von anderem Anwendungscode überschrieben worden sind.
  • Zu erweitern oder die Zeichenfolge zu ändern wird versucht.

Informationsquellen

In das <I> das STL ist, das zu VC++-threadsicher gehört, findet Sie Weitere Informationen über Sprachen- und Compiler-Visual C++-Probleme? </I>-Thema Microsoft Most Valuable Professional (MVP) auf der folgenden Website:
http://www.mvps.org/vcfaq

Eigenschaften

Artikel-ID: 813810 - Geändert am: Dienstag, 1. Juni 2004 - Version: 1.0
Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft Visual C++ 6.0 Service Pack 5
Keywords: 
kbthreadsync kbprb KB813810 KbMtde kbmt
Maschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 813810
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.
Disclaimer zu nicht mehr gepflegten KB-Inhalten
Dieser Artikel wurde für Produkte verfasst, für die Microsoft keinen Support mehr anbietet. Der Artikel wird deshalb in der vorliegenden Form bereitgestellt und nicht mehr weiter aktualisiert.

Ihr Feedback an uns