問題
我正在嘗試在 C/C 中宣告一個大型 2D 陣列(又名矩陣),但它僅在 Linux 上因段錯誤而崩潰。Linux 系統安裝的 RAM 比 macOS 筆記本電腦多得多,但它只會在 Linux 系統上崩潰。
我的問題是:為什么這只會在 Linux 上崩潰,而不是在 macOS 上?
這是一個重現該問題的小程式:
// C program to segfault on linux
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
cout << "Let's crash for no raisin! ??" << endl;
cout << "Int size: " << sizeof(int) << endl;
for (int n=1012; n < 2000; n ) {
cout << "Declaring Matrix2D of size: " << n << "x" << n << " = " << n*n << endl;
cout << "Bytes: " << n*n*sizeof(int) << endl;
// segfault on my machine at 1448x1448 = 8386816 bytes
int Matrix2D[n][n];
// these two lines can be commented out and the program still reaches segfault
// int* pM2D = (int*)malloc(n*n*sizeof(int));
// free(pM2D);
}
return 0;
}
編譯: g -Wall -g -o segfault segfault.cpp
輸出
Linux
Linux 系統安裝了 64 GiB RAM!
$ ./segfault ; free --bytes
Let's crash for no raisin! ??
Int size: 4
[...SNIP...]
Declaring Matrix2D of size: 1446x1446 = 2090916
Bytes: 8363664
Declaring Matrix2D of size: 1447x1447 = 2093809
Bytes: 8375236
Declaring Matrix2D of size: 1448x1448 = 2096704
Bytes: 8386816
Segmentation fault (core dumped)
total used free shared buff/cache available
Mem: 67400994816 11200716800 4125982720 412532736 52074295296 55054041088
Swap: 1023406080 824442880 198963200
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 256763
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 256763
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
蘋果系統
macOS 系統只安裝了 16 GB RAM!??
$ ./segfault ; sysctl -a | grep mem ;
Let's crash for no raisin! ??
Int size: 4
[...SNIP...]
Declaring Matrix2D of size: 1997x1997 = 3988009
Bytes: 15952036
Declaring Matrix2D of size: 1998x1998 = 3992004
Bytes: 15968016
Declaring Matrix2D of size: 1999x1999 = 3996001
Bytes: 15984004
kern.dtrace.buffer_memory_maxsize: 5726623061
kern.dtrace.buffer_memory_inuse: 0
kern.memorystatus_sysprocs_idle_delay_time: 10
kern.memorystatus_apps_idle_delay_time: 10
kern.memorystatus_purge_on_warning: 2
kern.memorystatus_purge_on_urgent: 5
kern.memorystatus_purge_on_critical: 8
vm.memory_pressure: 0
hw.memsize: 17179869184
machdep.memmap.Conventional: 17077571584
machdep.memmap.RuntimeServices: 524288
machdep.memmap.ACPIReclaim: 188416
machdep.memmap.ACPINVS: 294912
machdep.memmap.PalCode: 0
machdep.memmap.Reserved: 84250624
machdep.memmap.Unusable: 0
machdep.memmap.Other: 0
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 1
stack size (kbytes, -s) 65532
cpu time (seconds, -t) unlimited
max user processes (-u) 2784
virtual memory (kbytes, -v) unlimited
uj5u.com熱心網友回復:
盡管 ISO C 不支持可變長度陣列,但您似乎正在使用支持它們作為擴展的編譯器。
在行
int Matrix2D[n][n];
n可以有一個高達2000. 這意味著二維陣列可以有2000*2000元素,等于 400 萬。每個元素的大小為sizeof(int),4在 linux上是位元組。這意味著您在堆疊上總共分配了 16 兆位元組。這超出了堆疊的限制,導致堆疊溢位。
它在 MacOS 上沒有崩潰的原因可能是堆疊配置為更高的最大限制,或者可能是您的程式沒有崩潰,因為可變長度陣列的實作方式不同,因此程式沒有接觸 2D陣列,或者它可能正在接觸 2D 陣列,但只能以不會導致崩潰的方式。這些是編譯器的實作細節。
計算機上實際安裝的記憶體量無關緊要。重要的是作業系統中配置的最大堆疊限制。
如果您想使用比堆疊上允許的更大的記憶體量,您應該使用堆來代替。在這種情況下,您應該使用std::make_unique,operator new或來分配記憶體std::malloc。您還可以使用大多數 STL 容器,例如std::vector,即使您在堆疊上創建實際容器,它也會自動將其內容存盤在堆上。但是,請注意某些 STL 容器不會,例如std::array.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/408690.html
標籤:
上一篇:為不同演算法重塑機器學習輸入資料
