01/10/2018, 10:45

Khai báo mảng bên trong và bên ngoài main

em có thấy nhiều người dùng cách khai báo mảng bên ngoài hàm main trên C++, em có hỏi thì mn bảo là mảng khai báo bên ngoài main thì đc cấp nhiều phần tử hơn. Không biết như vậy có đúng ko ạ mong mn chỉ giúp ạ

HK boy viết 12:51 ngày 01/10/2018

Khai báo mảng bên trong hàm main: bộ nhớ stack
Khai báo mảng bên ngoài hàm main: bộ nhớ heap
Vì bộ nhớ stack có dung lượng thấp hơn bộ nhớ heap nên nếu khai báo mảng > 10000 phần tử thì đưa ra ngoài main.

hoàng viết 12:54 ngày 01/10/2018

nhưng mà a cho em hỏi là nếu em dùng cấp phát động thì nó sẽ đc lưu vào bộ nhớ heap phải ko ạ.
Như vậy thì em vẫn bị lỗi tràn mảng mà ko rõ nguyên nhân

HK boy viết 12:48 ngày 01/10/2018

Nếu cấp phát động trong main() thì vẫn là vào bộ nhớ stack (?), như thế thì mới tràn mảng

hoàng viết 12:56 ngày 01/10/2018

à vâng em cảm ơn ạ

viết 12:48 ngày 01/10/2018

cấp phát động là lên heap rồi, đâu ra ở stack nữa, ở trong main ko phải là vấn đề.

còn khai báo mảng ở “ngoài main” chắc ở đây là mảng global. Những biến global sẽ được đặt ở vùng data, vùng này được load lên khi chương trình khởi động, ko phải là stack hay heap gì cả.

en.wikipedia.org

Data segment

In computing, a data segment (often denoted .data) is a portion of an object file or the corresponding virtual address space of a program that contains initialized static variables, that is, global variables and static local variables. The size of this segment is determined by the size of the values in the program's source code, and does not change at run time. The data segment is read-write, since the values of variables can be altered at run time. This is in contrast to the read-only data segm...

vùng data đó.

khai báo 1 biến trong hàm thì biến đó nằm trên stack. Còn hễ gọi malloc calloc realloc v.v… gì thì con trỏ trả về trỏ tới vùng nhớ được cấp phát trên heap. Mấy biến global thì nó là global luôn, tới khi chương trình kết thúc thì nó mới biến mất, khác với biến trên stack biến mất khi ra khỏi phạm vi của nó, hay biến trên heap biến mất tùy ý.

hoàng viết 12:57 ngày 01/10/2018

vậy thì có phải nếu là khai báo mảng theo kiểu toàn cục thì được cấp phát số lượng phần tử lớn không ạ mong anh giúp em giải đáp ở phần mở đầu ạ

Hung viết 12:52 ngày 01/10/2018

Không bạn, global data 1 ở phân vùng bss, hoặc ở phân vùng data, mà bss và data bị giới hạn.

Thêm nữa, không bao giờ sử dụng biến toàn cục.

hoàng viết 12:51 ngày 01/10/2018

spoj.com

SPOJ.com - Problem P144SUMA

...


vậy trong bài này ạ nếu dùng mảng mà lưu số lượng lớn như vậy thì khai báo bính thường hay cấp phát động có được ko ạ. em dùng cấp phát động thì bị tràn mảng mà ko rõ.
Em có hỏi qua thì mn bảo là phải khai báo ngoài main. Em ko hiểu rõ lắm nên mới hỏi mn

Hung viết 12:48 ngày 01/10/2018

Mà bạn dùng std::vector cho gọn, khỏi lo về cấp phát và thu hổi bộ nhớ.
Mình thấy đề tài không cấm sử dụng thư viện.

hoàng viết 13:01 ngày 01/10/2018

dạ đối với vector thì em cũng biết cách dùng nhưng tại xuất hiện vấn đề mới này nên em muốn hiểu rõ hơn ạ

Hung viết 12:48 ngày 01/10/2018

Vậy bạn khai báo 1 biến array kiểu con trỏ rồi khởi tạo nó trong hàm main().

int *array = new int[size];

Rồi trả vùng nhớ lại cho OS

delete[] array;

Tránh khai báo kiểu này, vì nó tạo ra local variable

int array[5];
hoàng viết 12:46 ngày 01/10/2018

em cấp phát động như vậy mà a, chảng qua là thiếu hàm delete thôi ạ
nhưng vẫn bị tràn mảng

Hung viết 12:48 ngày 01/10/2018

Kiểm tra biến n đi, code viết đúng rồi.

hoàng viết 12:53 ngày 01/10/2018

Biến n của em có vấn đề gì ạ

Hung viết 12:51 ngày 01/10/2018

Biến n không có vấn đề gì cả, bạn nói là lỗi tràn mảng thì chỉ có lý do là do biến n lớn quá. Nên kiểm tra lại cho chắc. Đặt breakpoint hay in ra console cũng được.

Tao Không Ngu. viết 12:51 ngày 01/10/2018

Hi hoàng.
Bạn cần làm rõ vấn đề cấp phát bộ nhớ và truy xuất vùng nhớ không được phép.

  1. Nếu bạn cấp phát không được (thiếu ram cấp phát nhiều quá dò bộ nhớ v.v.v…) thì con trỏ của bạn sẽ null. Trong trườn hợp bạn truy xuất ra ngoài vùng nhớ được cấp phát thì do index của bạn có vấn đề hoặc vung nhớ đó bị giải phóng không liên quan gì đến việc cấp phát bộ nhớ.
  2. Về vị trí cấp phát thì như các bạn đã nói ở trên.
  3. Về code của bạn thì mình thấy dòng 14 hơi có vấn đề. Bạn khai báo một mảng char trong khối lệnh thì sau khi kết thúc khối lệnh đó vung nhớ đó bị giải phóng và đồng nghĩa với việc các địa chỉ bạn gán vào a[i] đều là các vung nhớ không được cấp phát.

P/S Chưa chay thử code vì ngại gõ lại. Mình coded C# là chính.

viết 12:54 ngày 01/10/2018

“tràn mảng” là cái gì??

1 dòng có 2 ký tự 01 10, mà biến s được khai báo là char s[2]; vậy có đủ ko? Chuỗi C-string cần có thêm ký tự nào sau cùng? Phải khai báo là char s[3]; mới đúng.

lần sau đọc chuỗi bạn cứ xài thẳng string#include <string> là được. Đừng xài mảng ký tự. Kệ mẹ thằng nào nói string chậm hơn. Làm đúng cái đã.

khai báo string s; rồi cin >> s; cho khỏe, khỏi cần biết gì về độ dài cái chuỗi đó cần 2 hay 3 ký tự. Cái vấn đề này nhảm nhí ko liên quan tới bài toán

edit: chắc phứ tạp hơn, hehe

Hung viết 12:54 ngày 01/10/2018

Đề bài nhận input từ file, chủ topic chỉ nhận theo đúng format của file. Tuy nhiên, chủ thớt lại không biết thao tác với file nên dùng cin. Dòng đầu tiên trong file là biến n nên bản cin cũng nhận n.

phần s[2] hình như chỉ đọc 1 kí tự: 1 hoặc 0. Ví dụ input:

5
10
01
10
10
10

sau khi nhập mảng a thành

// bỏ chấm
1 0 . 0 1 . 1 0 . 1 0 . 1 0 . 1 0

À hiểu, mảng a kích thước 2*n thì chạy mới được (trong lúc đang viết bình luận)

viết 12:55 ngày 01/10/2018

nếu vế phải của cin >>char * thì cin nó đọc tới khi nào gặp khoảng trắng mới dừng mà. Input là “123213 123” thì nó đọc hết “123213” cộng thêm ký tự null cuối cùng = 7 ký tự vô biến char * đó luôn, nên mới gây ra tràn mảng.

Hung viết 12:53 ngày 01/10/2018

Mình cũng mập mờ chỗ đó, không biết chủ thớt nhập kiểu nào.

Bài liên quan
0