2010-06-16 34 views
5

Mã này tạo ra lỗi phân đoạn trong quá trình khai báo mảng. Tôi đang bối rối là tại sao điều này xảy ra. Tôi cố ý chọn 2000000000 làm giá trị vì nó dưới 2^31 và có thể vừa với một biến số nguyên.Lập trình C, tại sao khai báo mảng lớn này tạo ra lỗi phân đoạn?

int main() 
{ 

    int nums_size = 2000000000; 

    int nums[nums_size]; 

    int i; 
    for(i = 0; i < nums_size; i++) { 
     nums[i] = i; 
    } 


    return 0; 

} 

Trả lời

21

Vâng, một điều, đó là hai tỷ số nguyên. Nếu bạn có không gian địa chỉ 32 bit và int có kích thước bốn byte trên nền tảng của bạn (điển hình cho nền tảng 32 bit), bạn không thể lưu trữ nhiều số nguyên, dấu chấm.

Mặc dù vậy, bạn chỉ có nhiều không gian có sẵn cho bạn trên ngăn xếp, nơi có các biến tự động.

Nếu bạn cần một mảng thực sự lớn, bạn nên dyncamically phân bổ nó bằng cách sử dụng malloc() (và nếu bạn làm như vậy, hãy chắc chắn để giải phóng nó bằng cách sử dụng free() khi bạn đang thực hiện với nó!).

+0

Thậm chí nếu không phải vậy, 2000000000 * 4 = 8.000.000.000 byte trên nền tảng 32 bit. Đó là gần 2^33, đó là nhiều hơn bộ nhớ có sẵn. –

+0

@ Chris: Vâng - Tôi đã không thực sự đếm số không cho đến sau khi tôi đăng. Đó là rất nhiều số nguyên! –

+0

Cũng có thể phân bổ các mảng rất lớn với thời gian lưu trữ tĩnh. – caf

4
int nums_size = 2000000000; 

int nums[nums_size]; 

Không có nghĩa là 2000000000 byte ints, nó có nghĩa là 2000000000 yếu tố loại int, mà trên nền tảng 32 bit có nghĩa là bạn đang tiêu thụ gần 8GB bộ nhớ - điều này là không thể.

+0

... và trên ngăn xếp!- Kaboom! –

3

Bạn đang phân bổ một mảng khổng lồ trên ngăn xếp. Hầu như không có trình biên dịch C/C++ nào xử lý chính xác.

Bạn có thể thoát khỏi việc di chuyển nó vào các hình cầu (sẽ phân bổ không gian tĩnh bằng cách ánh xạ bộ nhớ trong thời gian biên dịch) hoặc bằng cách chuyển sang mảng malloc 'd.

Tất nhiên, vẫn còn rất nhiều bộ nhớ để yêu cầu tại một thời điểm, nhưng ít nhất các phương pháp tôi đang đề cập sẽ tránh được ngay lập tức segfault.

+1

Trình biên dịch sẽ xử lý chính xác (nếu nó nằm trong kích thước bộ nhớ 2^32), nhưng hệ điều hành sẽ không cho phép ngăn xếp để có được kích thước lớn. –

+0

không chỉ C/C++ khá nhiều bất kỳ ngôn ngữ nào dựa trên phân bổ stack (tức là hầu như tất cả chúng) – Spudd86

0

Phiên bản này chạy tốt trên máy tính của tôi:

const int nums_size = 2000000000; 
int nums[nums_size]; 

int main() 
{ 
    int i; 
    for(i = 0; i < nums_size; i++) { 
     nums[i] = i; 
    } 

    return 0; 
} 

(Vâng, chúng ta hãy trung thực Nó bắt đầu tốt, nhưng nhanh chóng đi vào trao đổi..)

+0

Và tôi đoán phiên bản của bạn chạy trên nền tảng 64bit. Từ 2^31 bình luận của mình, anh ấy chắc chắn không chạy một hệ điều hành 64bit. –

+0

-1 vì có nhiều bộ nhớ hơn tôi (chỉ đùa thôi). – cdonner

+0

@Chris 2^31 bình luận không cho bạn biết bạn đang chạy 32-bit hay 64-bit. Tôi nghĩ gcc mặc định là int-bit 32 bit trên nền tảng 64 bit. – sigfpe

2

biến địa phương được cấp phát trên stack . Có một không gian ngăn xếp cố định (thường là 1MB – 8MB, thay đổi theo hệ điều hành) được cung cấp cho ứng dụng. Quy tắc chung là sử dụng malloc() để phân bổ lượng lớn dữ liệu.

1

Câu trả lời cho câu hỏi của bạn rất đơn giản: stackoverflow. Không, không, không phải là trang web, nhưng quá trình thực sự của "tràn ngăn xếp". Bạn không có đủ stack để lưu trữ mảng đó. Đơn giản vậy thôi. Làm điều này trên các hệ thống hạn chế bộ nhớ là điên rồ thuần khiết. Xem thêm this question.

Các vấn đề liên quan