2015-08-27 16 views
11

& bir size her zaman va_end() aramak gerektiğini kurulur:Va_end çağrılmadan önce longjmp işleminin tamam mı? Bu Q

What exactly is va_end for? Is it always necessary to call it?

Ama ya kod longjmp yılların bir parça sen va_end ulaşmadan? Va_end'in parçasının iyi olacağına dair bir söz var mı? Ya da kavramsal olarak (örneğin)va_start()'da bir bellek ayırma yapabilir mi?

+3

"Longjmp" i çağırmadan önce "va_end" i çağırmanız gerekeceğini sanıyorum, aynı şekilde "free()" yapmalısınız, –

+0

üzerinden atlanan herhangi bir kötüleşme, sorunun noktası değil mi? –

+0

@WeatherVane Evet. Soru, her argüman maddesini işlemek için ne yapıyorsanız, longjmp olabilir. Eğer öyleyse, o zaman değişken kodlarını almak ve aramalarınızı yapmadan önce başka bir yere koymak zorundasınız ... ama hangi yer? Büyüklük sınırına sahip sınırlı bir yığın dizisi. Hangi va_args zaten o yer olarak hizmet edebilirdi ... ve gerçek uygulamalarda, genellikle iyi olurdu. Ama standardın söz vermesi olası değil. – HostileFork

cevap

8

C99 rationale açıkça va_start Eğer söz konusu tahmin tam olarak ne, va_end tarafından serbest biter bellek tahsis edebilir belirtmektedir:

7.15.1.2 va_copy makro

[...

30 Çok daha basit bir yaklaşım, argümanların işlenmesini temsil etmek için kullanılan va_list nesnesini kopyalamaktır. Ancak, için güvenli bir yol yoktur, çünkü bu nesne, va_start makrosu tarafından tahsis edilen ve va_end makrosu tarafından yok edilen belleğe işaretçiler içerebilir.
Yeni va_copy makrosu bu güvenli mekanizmayı sağlar.

[...]

Yani evet, bir longjmp önce va_end çağırmak gerekir. En azından böyle bir uygulamada bir bellek sızıntısı olabilir.


Sözde Piramit OSX bellek ayırmalarını va_start tarafından yapılmıştır bir uygulama vardı. İşlev argümanları kayıtlara geçirildi. Bu, değişken fonksiyonlar için bile geçerliydi. ANSI C'nin fonksiyon prototiplerinin icadını önceden yapmış olabilir, bu da arayanın değişken bir fonksiyonla uğraşıp uğraşmadığını bilmeyeceği anlamına gelir. va_start tahsis edilmiş bellek, fonksiyon parametresi değerlerini va_arg'a kolayca erişebilecek şekilde saklamak için. Ayrılan belleği va_end serbest bıraktı.

va_start ve va_end Onun uygulanması aslında ANSI C zaten uygulanmasının izin verilmeyen bu yüzden, dengesiz parantez kullanılan biriydi çünkü sözdizimsel va_start ve va_end eşleşen gerekmez, ancak aynı prensip eşleşen parantez yerken çalışmak için yapılmış olabilir.

Bu uygulama hakkında çok az somut bilgi bulabilirim, sadece 90'ların başında, 80'lerin başında Usenet'teki parçalar ve parçalar. Bulduğum şey eksik veya hatta yanlış yanlış olabilir. Özellikle bu uygulamayı kendileri kullanan herkes tarafından daha fazla ayrıntı çok açıktır.

+0

Bazı en azından burada yuvarlak mantıklı. Oylama. –

+2

Ayrıca bence “va_end” mantığını içeren pek çok uygulamada, bu bir “yapma” işlemi; ama buna ihtiyaç duyan uygulamalar muhtemelen ona çok ihtiyaç duyuyor. 'Kötü' olsa da çok belirsiz. – cremno

+0

* "İhtiyacı olan uygulamalar muhtemelen ona çok ihtiyaç duyar" * ... heh, oldukça komik. :-) – HostileFork

2

bir genel değişken (her zamanki desen) saklanan bir jmp_buff kullanıyorsanız, muhtemelen bunun bir kopyasını yapmak ve böylece longjmp dış arayan yerine, kod gidecek setjmp kullanmak için güvenli olmalıdır ; longjmp durumunda, kodunuz, arabelleğin saklanan kopyasını kullanarak va_end ve longjmp'u arayabilir; Kodunuz normal olarak çıkarsa, geri dönmeden önce global arabelleği geri yüklemesi gerekir.

+0

@HostileFork pratik şartlarda, eğer kodunuz önemsiz 'va_end' olan bir platformda çalıştırılamazsa, o zaman muhtemelen sorunu görmezden gelirim. Ancak, muhtemelen, atlanan kodda oluşan yığın ayırmalarla başa çıkmak için yerinde bir şeyler yapmanız gerekir. –

İlgili konular