Debian GNU / Linux 9 sistemimde, bir ikili yürütüldüğünde,
- yığın başlatılmadı ancak
- yığın sıfır başlatılır.
Neden?
Sıfır başlatmanın güvenliği desteklediğini varsayıyorum, ancak yığın için ise neden yığın için olmasın? Yığın da güvenliğe ihtiyacı yok mu?
Sorum bildiğim kadarıyla Debian'a özgü değil.
Örnek C kodu:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
const size_t n = 8;
// --------------------------------------------------------------------
// UNINTERESTING CODE
// --------------------------------------------------------------------
static void print_array(
const int *const p, const size_t size, const char *const name
)
{
printf("%s at %p: ", name, p);
for (size_t i = 0; i < size; ++i) printf("%d ", p[i]);
printf("\n");
}
// --------------------------------------------------------------------
// INTERESTING CODE
// --------------------------------------------------------------------
int main()
{
int a[n];
int *const b = malloc(n*sizeof(int));
print_array(a, n, "a");
print_array(b, n, "b");
free(b);
return 0;
}
Çıktı:
a at 0x7ffe118997e0: 194 0 294230047 32766 294230046 32766 -550453275 32713
b at 0x561d4bbfe010: 0 0 0 0 0 0 0 0
C standardı malloc()
elbette ayırmadan önce hafızayı temizlemeyi istemez , ancak C programım sadece gösterim amaçlıdır. Soru, C veya C'nin standart kütüphanesi hakkında bir soru değildir. Daha ziyade soru, çekirdek ve / veya çalışma zamanı yükleyicisinin neden yığını değil, yığını sıfırladığı sorusudur.
BAŞKA BİR DENEY
Sorum standart belgelerin gerekliliklerinden ziyade gözlemlenebilir GNU / Linux davranışı ile ilgili. Ne demek istediğimden emin değilseniz, daha sonra tanımlanamayan davranışları ( tanımlanmamış, yani C standardı söz konusu olduğunda) çağıran bu kodu deneyin :
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
const size_t n = 4;
int main()
{
for (size_t i = n; i; --i) {
int *const p = malloc(sizeof(int));
printf("%p %d ", p, *p);
++*p;
printf("%d\n", *p);
free(p);
}
return 0;
}
Makinemden çıktı:
0x555e86696010 0 1
0x555e86696010 0 1
0x555e86696010 0 1
0x555e86696010 0 1
C standardı ile ilgili olarak, davranış tanımsızdır, bu yüzden sorum C standardını dikkate almaz. malloc()
Her seferinde aynı adresi döndürmesi gerekmeyen bir çağrı, ancak bu çağrı, malloc()
her seferinde aynı adresi döndürdüğü için , yığıntaki belleğin her seferinde sıfırlandığını fark etmek ilginçtir .
Öte yandan, yığın sıfırlanmış gibi görünmüyordu.
GNU / Linux sisteminin hangi katmanının gözlenen davranışa neden olduğunu bilmediğim için, ikinci kodun makinenizde ne yapacağını bilmiyorum. Bunu deneyebilirsin.
GÜNCELLEME
@Kusalananda yorumlarda gözlemledi:
Değeri ne olursa olsun, OpenBSD'de çalıştırıldığında en son kodunuz farklı adresler ve (zaman zaman) başlatılmamış (sıfır olmayan) veriler döndürür. Bu açıkça Linux'ta tanık olduğunuz davranış hakkında hiçbir şey söylemiyor.
Sonucumun OpenBSD'deki sonuçtan farklı olması gerçekten ilginç. Görünüşe göre, deneylerim düşündüğüm gibi bir çekirdek (veya bağlayıcı) güvenlik protokolü değil, sadece bir uygulama artefaktı keşfetti.
Bu ışık altında, @mosvy, @StephenKitt ve @AndreasGrapentin'in aşağıdaki cevaplarının birlikte sorumu çözdüğüne inanıyorum.
Ayrıca bkz. Yığın Taşması: Malloc neden değerleri gcc cinsinden 0 olarak başlatır? (kredi: @bta).
new
C operatör ++ (aynı zamanda "yığın") Linux malloc'un için bir sargı () 'i; çekirdek "yığın" ne olduğunu bilmiyor ya da umursamıyor.