Aracılığıyla paylaş


sal anlama

Microsoft kaynak kodu ek açıklama dili (sal), bir işlev parametreleri, bunlarla ilgili yaptığı varsayımları ve sona erdiğinde kolaylaştıran garanti nasıl kullandığını açıklamak için kullanabileceğiniz ek açıklamalar sağlar.Ek açıklamaları üstbilgi dosyasında tanımlanmış olan <sal.h>.c++ için Visual Studio kod analizi sal ek açıklamalar işlevleri çözümlemesini değiştirmek için kullanır.Windows Sürücü Geliştirme sal 2.0 hakkında daha fazla bilgi için bkz: sal 2.0 ek açıklamalar için Windows sürücüleri.

Özgün olarak, c ve c++ amacı ve invariance tutarlı bir şekilde ifade etmek geliştiriciler için yalnızca sınırlı yollar sunar.sal ek açıklamaları kullanarak, böylece onları kullanan geliştiriciler daha iyi nasıl kullanıldıklarını anlamak daha ayrıntılı işlevlerinizi açıklayabilirsiniz.

sal nedir ve neden kullanmalısınız?

Kısacası, sal kodunuzu kontrol edin derleyici bildirmek üzere ucuz bir yol değil.

Hh916383.collapse_all(tr-tr,VS.110).gifKod sal daha değerli yapar

sal, insanlar için ve kod çözümleme araçları için kod tasarımınızı daha anlaşılır yapmak yardımcı olabilir.c çalışma zamanı işlevine gösteren Bu örnek göz önünde memcpy:

void * memcpy(
   void *dest, 
   const void *src, 
   size_t count
);

Bu işlev yaptıklarını anlayabilirsiniz?Bir işlev uygulanan ya da adlı programı doğruluğu sağlamak için belirli özelliklerini tutulması gereken.Yalnızca bir örnek gibi bir bildirimi bakarak, bunların ne olduğunu bilmiyorum.sal ek açıklamalar olmadan, belgeleri veya kod açıklamaları yararlanmayı yoktur.İçin msdn belgeleri işte memcpy diyor:

"Kopya dest için src bayt sayma.Kaynak ve hedef üst üste gelirse, memcpy davranışı tanımsızdır.Memmove çakışan bölgeleri işlemek için kullanın.Güvenlik notu: veya kaynak arabelleği daha büyük boyut hedef arabelleğin aynı olduğundan emin olun.Daha fazla bilgi için arabellek taşmasına neden önleme bakın."

Belgeleri birkaç program doğruluğu sağlamak için belirli özelliklerini korumak kodunuzu olduğunu Öner bit bilgi içerir:

  • memcpykopya count gelen kaynak arabelleği hedef arabelleğin bayt bayt.

  • Hedef arabellek en az kaynak arabelleği kadar büyük olmalıdır.

Ancak, derleyici belgelerine veya resmi olmayan açıklamalar okuyamıyor.İki arabellekleri arasında bir ilişki olduğunu bilmesi gerekmese ve count, ve onu da etkili bir şekilde bir ilişki hakkında tahmin edilemez.sal, aşağıda gösterildiği gibi özellikleri ve uygulama işlevi hakkında daha fazla netlik sağlayabilir:

void * memcpy(
   _Out_writes_bytes_all_(count) void *dest, 
   _In_reads_bytes_(count) const void *src, 
   size_t count
);

Bu ek açıklamalar bilgi msdn belgelerindeki benzer, ancak daha kısa oldukları ve anlamsal bir desen takip etmeleri dikkat edin.Bu kodu okurken, bu işlev özelliklerini ve nasıl arabellek taşması güvenlik sorunlarını da önlersiniz kolayca anlayabilirsiniz.sal sağlar anlamsal desenler bile daha iyi verimlilik ve otomatik kod analizi araçlarının olası hataların erken bulma verimliliğini artırabilirsiniz.Birisi buggy uygulaması, yazar düşünün wmemcpy:

wchar_t * wmemcpy(
   _Out_writes_all_(count) wchar_t *dest, 
   _In_reads_(count) const wchar_t *src, 
   size_t count)
{
   size_t i;
   for (i = 0; i <= count; i++) { // BUG: off-by-one error
      dest[i] = src[i];
   }
   return dest;
}

Bu uygulama ortak bir kapalı tek hatası içeriyor.Neyse ki, kod yazar sal arabellek boyutu ek açıklamayı dahil — kod çözümleme aracını bu işlev analiz ederek hatayı yakalamak.

Hh916383.collapse_all(tr-tr,VS.110).gifSAL Basics

sal dört temel tür kullanım desenine göre kategorize parametreleri tanımlar.

Kategori

Ek Açıklama parametresi

Tanımlama

Giriş işlevi denir.

_In_

Veriler, çağrılan işleve geçirilen ve salt okunur olarak kabul edilir.

Giriş işlevi adı verilen ve arayan kişiye çıktı

_Inout_

Kullanılabilir veri işlevi geçirilir ve potansiyel olarak değiştirilir.

Arayana çıktı

_Out_

Arayanın yalnızca çağrılan işlev yazmak alan sağlar.Çağrılan işlev bu alana veri yazar.

Arayana işaretçisinin çıktı

_Outptr_

Gibi Arayan için çıktı.Çağrılan işlev tarafından döndürülen değeri bir işaretçidir.

Bu dört temel ek açıklamalar daha açık olarak çeşitli şekillerde yapılabilir.Varsayılan olarak, işaretçiyi açıklamalı parametreleri gerekli olarak kabul edilir — null olmaması gerekir başarılı olması işlev.En yaygın olarak kullanılan temel ek açıklamaları türevini işaretçi parametresi isteğe bağlı olduğunu gösterir — null ise, işlev hala kendi iş yaparak başarabilir.

Bu tablo, gerekli ve isteğe bağlı parametreler arasında ayrım nasıl gösterir:

Parametreler gereklidir

Parametreler isteğe bağlıdır

Giriş işlevi denir.

_In_

_In_opt_

Giriş işlevi adı verilen ve arayan kişiye çıktı

_Inout_

_Inout_opt_

Arayana çıktı

_Out_

_Out_opt_

Arayana işaretçisinin çıktı

_Outptr_

_Outptr_opt_

Bu ek açıklamalar başlatılmamış olası değerler tanımlamak ve geçersiz null işaretçi resmi ve doğru bir şekilde kullanır.Gerekli bir parametre null geçirerek kilitlenmeye neden olabilir veya bir "başarısız" hata kodu döndürülen neden olabilir.Her iki durumda da işlev işini yaparak başarılı olamaz.

sal örnekleri

Bu bölümde temel sal ek açıklamaları için kod örnekleri gösterir.

Hh916383.collapse_all(tr-tr,VS.110).gifHatalarını bulmak için Visual Studio kod çözümleme aracını kullanma

Örneklerde, Visual Studio kod çözümleme aracı sal ek açıklamalar ile birlikte kod hatalarını bulmak için kullanılır.Bunu yapmak nasıl olur.

Visual Studio kod çözümleme araçları ve sal kullanmak için

  1. Visual Studio'da sal ek açıklamalar içeren bir c++ projesini açın.

  2. Menü çubuğunda Seç Yapı, Çözüm üzerinde çalışan kod analizi.

    Bu bölümde _In_ örneği göz önünde bulundurun.Kod Analizi üzerinde çalıştırırsanız, bu uyarı görüntülenir:

    C6387 Geçersiz parametre değeri'pInt', '0' olabilir: Bu 'InCallee' işlevi için belirtimine uymayan.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _In_ ek açıklama

_In_ Ek açıklama gösterir:

  • Parametre geçerli olmalı ve değiştirilmeyecek.

  • İşlev yalnızca tek elemanlı arabelleğinden okuyacaktır.

  • Arayanın arabelleği sağlamak ve yeniden başlatmak gerekir.

  • _In_"salt okunur" belirtir.Uygulamak için ortak bir hata mı _In_ sahip olması gereken bir parametre için _Inout_ ek açıklama yerine.

  • _In_ancak üzerinde işaretçiyi fazla ilerleyemezdik Çözümleyicisi tarafından göz ardı izin verilir.

void InCallee(_In_ int *pInt)
{
   int i = *pInt;
}

void GoodInCaller()
{
   int *pInt = new int;
   *pInt = 5;

   InCallee(pInt);
   delete pInt;   
}

void BadInCaller()
{
   int *pInt = NULL;
   InCallee(pInt); // pInt should not be NULL
}

Bu örnek Visual Studio kod analizi kullanırsanız, arayanlar için başlatılmış bir arabellek Null olmayan bir işaretçi geçirmek doğrular pInt.Bu durumda, pInt işaretçi null olamaz.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _In_opt_ ek açıklama

_In_opt_aynı _In_, giriş parametresi null olmasına izin verilen ve bu nedenle, işlev için denetlemelisiniz olmasıdır.

void GoodInOptCallee(_In_opt_ int *pInt)
{
   if(pInt != NULL) {
      int i = *pInt;
   }
}

void BadInOptCallee(_In_opt_ int *pInt)
{
   int i = *pInt; // Dereferencing NULL pointer ‘pInt’
}

void InOptCaller()
{
   int *pInt = NULL;
   GoodInOptCallee(pInt);
   BadInOptCallee(pInt);
} 

Visual Studio kod analizi arabellek erişen önce işlev null denetler doğrular.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _Out_ ek açıklama

_Out_geçirilen null olmayan işaretçi işaret eden bir Elemanı Tamponu ve öğe fonksiyonu başlatır genel bir senaryoyu destekler.Arayanın arabelleği çağırmadan önce başlatmak gerekmez; Çağrılan işlev döndürmeden önceki başlatmak üzere vaat ediyor.

void GoodOutCallee(_Out_ int *pInt)
{
   *pInt = 5;
}

void BadOutCallee(_Out_ int *pInt)
{
   // Did not initialize pInt buffer before returning!
}

void OutCaller()
{
   int *pInt = new int;
   GoodOutCallee(pInt);
   BadOutCallee(pInt);
   delete pInt;
} 

Visual Studio kod çözümleme aracını doğrular Arayanın arabelleği için null olmayan bir işaretçi geçirir pInt ve onu döndürmeden önce arabellek işlevi tarafından başlatılır.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _Out_opt_ ek açıklama

_Out_opt_aynı _Out_, parametre null olmasına izin verilen ve bu nedenle, işlev için denetlemelisiniz olmasıdır.

void GoodOutOptCallee(_Out_opt_ int *pInt)
{
   if (pInt != NULL) {
      *pInt = 5;
   }
}

void BadOutOptCallee(_Out_opt_ int *pInt)
{
   *pInt = 5; // Dereferencing NULL pointer ‘pInt’
}

void OutOptCaller()
{
   int *pInt = NULL;
   GoodOutOptCallee(pInt);
   BadOutOptCallee(pInt);
} 

Visual Studio kod analizi doğrular, önce null denetler bu işlev pInt başvuru yapıldı ve pInt döndürmeden önceki arabellek işlevi tarafından başlatılmış olan null değil.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _Inout_ ek açıklama

_Inout_işlev tarafından değiştirilebilir bir işaretçi parametresi açıklama eklemek için kullanılır.İşaretçiyi çağırmadan önce başlatılmış geçerli verilere işaret etmelidir ve onu değişse dahi, onu hala geçerli bir değer getirisi olması gerekir.Ek açıklamayı işlevi ücretsiz olarak okuyabilir ve tek öğeli arabelleğe yazma belirtir.Arayanın arabelleği sağlamak ve yeniden başlatmak gerekir.

[!NOT]

Gibi _Out_, _Inout_ değiştirilebilir bir değere uygulamanız gerekir.

void InOutCallee(_Inout_ int *pInt)
{
   int i = *pInt;
   *pInt = 6;
}

void InOutCaller()
{
   int *pInt = new int;
   *pInt = 5;
   InOutCallee(pInt);
   delete pInt;
}

void BadInOutCaller()
{
   int *pInt = NULL;
   InOutCallee(pInt); // ‘pInt’ should not be NULL
} 

Visual Studio kod analizi doğrular arayanlar için başlatılmış bir arabellek null olmayan bir işaretçi geçirmek pIntve dönüş önce pInt yine de boş olmayan ve arabellek başlatıldı.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _Inout_opt_ ek açıklama

_Inout_opt_aynı _Inout_, giriş parametresi null olmasına izin verilen ve bu nedenle, işlev için denetlemelisiniz olmasıdır.

void GoodInOutOptCallee(_Inout_opt_ int *pInt)
{
   if(pInt != NULL) {
      int i = *pInt;
      *pInt = 6;
   }
}

void BadInOutOptCallee(_Inout_opt_ int *pInt)
{
   int i = *pInt; // Dereferencing NULL pointer ‘pInt’
   *pInt = 6;
}

void InOutOptCaller()
{
   int *pInt = NULL;
   GoodInOutOptCallee(pInt);
   BadInOutOptCallee(pInt);
} 

Visual Studio kod analizi doğrular önce arabellek erişir ve bu işlev için null denetler pInt döndürmeden önceki arabellek işlevi tarafından başlatılmış olan null değil.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _Outptr_ ek açıklama

_Outptr_bir işaretçi döndürmek için tasarlanmış bir parametre açıklama eklemek için kullanılır.Parametre null olmamalı ve çağrılan işlev null olmayan bir işaretçi döndürür ve bu işaretçiyi başlatılmış verilere işaret eder.

void GoodOutPtrCallee(_Outptr_ int **pInt)
{
   int *pInt2 = new int;
   *pInt2 = 5;

   *pInt = pInt2;
}

void BadOutPtrCallee(_Outptr_ int **pInt)
{
   int *pInt2 = new int;
   // Did not initialize pInt buffer before returning!
   *pInt = pInt2;
}

void OutPtrCaller()
{
   int *pInt = NULL;
   GoodOutPtrCallee(&pInt);
   BadOutPtrCallee(&pInt);
} 

Visual Studio kod analizi doğrular arayan bir null olmayan işaretçi geçtiği *pInt, ve onu döndürmeden önce arabellek işlevi tarafından başlatılır.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _Outptr_opt_ ek açıklama

_Outptr_opt_aynı _Outptr_, isteğe bağlı parametre olması dışında — arayan bir null işaretçi parametresi iletebilirsiniz.

void GoodOutPtrOptCallee(_Outptr_opt_ int **pInt)
{
   int *pInt2 = new int;
   *pInt2 = 6;

   if(pInt != NULL) {
      *pInt = pInt2;
   }
}

void BadOutPtrOptCallee(_Outptr_opt_ int **pInt)
{
   int *pInt2 = new int;
   *pInt2 = 6;
   *pInt = pInt2; // Dereferencing NULL pointer ‘pInt’
}

void OutPtrOptCaller()
{
   int **ppInt = NULL;
   GoodOutPtrOptCallee(ppInt);
   BadOutPtrOptCallee(ppInt);
} 

Visual Studio kod analizi doğrular, önce null denetler bu işlev *pInt başvuru yapıldı ve onu döndürmeden önce arabellek işlevi tarafından başlatılır.

Hh916383.collapse_all(tr-tr,VS.110).gifÖrnek: _Success_ birlikte ek açıklama ile _Out_

Ek açıklamalar çoğu nesnelere uygulanır.Özellikle, tam bir işlev açıklama ekleyebilirsiniz.Bir işlevin en belirgin özellikleri, başarılı veya başarısız, biridir.Ancak işlev başarı veya başarısızlık gibi bir arabellek boyutu arasındaki ilişkiyi, c/C++ express olamaz.Kullanarak _Success_ ek açıklama, benzer bir işlev için hangi başarı diyebilirsiniz.Parametre _Success_ ek açıklamadır yalnızca bir ifade doğru olduğunda işlev başarılı olduğunu gösterir.İfadede ek açıklama ayrıştırıcı işleyen her şey olabilir.İşlev başarılı olduğunda etkilerini işlevi döndükten sonra ek açıklamaları yalnızca uygulanabilir.Bu örnek gösterir nasıl _Success_ etkileşimde _Out_ doğru şeyi yapmak için.Anahtar sözcüğünü kullanabilirsiniz return dönüş değeri göstermek için.

_Success_(return != false) // Can also be stated as _Success_(return)
bool GetValue(_Out_ int *pInt, bool flag)
{
   if(flag) {
      *pInt = 5;
      return true;
   } else {
      return false;
   }
}

_Out_ Ek açıklama Arayanın arabelleği için null olmayan bir işaretçi geçirir Analysis doğrulamak için Visual Studio kod neden pInt, ve onu döndürmeden önce arabellek işlevi tarafından başlatılır.

sal en iyi yöntem

Hh916383.collapse_all(tr-tr,VS.110).gifVarolan kodu için ek açıklamalar ekleme

sal güvenlik ve güvenilirlik kodunuzun geliştirmenize yardımcı olabilecek güçlü bir teknolojidir.sal öğrendikten sonra yeni yetenek için günlük işlerinizde uygulayabilirsiniz.Yeni kod tasarım boyunca tarafından sal tabanlı belirtimleri kullanabilirsiniz; eski kod içinde ek açıklamalar ekleyebilme ve böylece, güncelleştirme her zaman faydaları artırmak.

Microsoft ortak üstbilgileri zaten açıklama.Bu nedenle, projelerinizde, ilk yaprak düğüm işlevleri ve en yüksek faydayı elde etmek için Win32 API çağrısı işlevlerini açıklama emin öneririz.

Hh916383.collapse_all(tr-tr,VS.110).gifNe zaman ı açıklama?

Bazı yönergeler verilmiştir:

  • İşaretçiyi tüm parametreleri ek açıklama ekleyebilirsiniz.

  • Kod Analizi arabellek ve işaretçi emniyet sağlayabilirsiniz, böylece değer aralığı ek açıklamaları açıklama ekleyin.

  • Kilitleme kuralları ve kilitleme yan etkileri ek açıklama ekleyebilirsiniz.Daha fazla bilgi için bkz. Kilitlenme Davranışını Yorumlama.

  • Sürücü özellikleri ve diğer etki alanına özgü özellikleri açıklama ekleyin.

Veya tüm parametreleri boyunca hedefi, temiz yapmak ve ek açıklamalar yapılmış denetlemek kolaylaştırmak için açıklama ekleyebilirsiniz.

İlgili Kaynaklar

Kod analiz ekibi Web günlüğü

Ayrıca bkz.

Başvuru

İşlev Parametrelerini ve Dönüş Değerlerini Açıklama

İşlev Davranışını Yorumlama

Yapıları ve Sınıfları Yorumlama

Kilitlenme Davranışını Yorumlama

Açıklamanın Ne Zaman ve Nereye Uygulanacağını Belirtme

En İyi Yöntemler ve Örnekler (SAL)

Diğer Kaynaklar

c/C++ kod hataları azaltmak için sal açıklamaları kullanma