30/09/2018, 21:07
Lỗi cấp phát động
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
void capphat(int *xPtr, int &n);
void nhap(int *xPtr, int n);
int main()
{
int * xPtr, n;
capphat( xPtr, n);
printf("%d",n);
nhap(xPtr, n);
getch();
return 0;
}
void capphat( int * xPtr, int &n)
{
printf("Nhap vao so phan tu cua mang : ");
scanf("%d",&n);
xPtr = (int *) calloc(n , sizeof(int));
}
void nhap(int * xPtr, int n)
{
for(int i =1 ; i<= n; i++)
{
printf("Nhap vap phan tu thu %d : ",i);
scanf("%d",xPtr+ i);
}
}
Bài liên quan
Coi
int *
là một kiểu thì muốn thay đổi nó bạn có thể truyền qua con trỏint* *xPtr
hoặc tham chiếuint* &xPtr
cậu nó rõ lại đi. cậu ơi. t mới học. hic
Ý Gió là
xPtr
có kiểu dữ liệuint*
lưu giá trị địa chỉ, khi truyền tham số vào hàmcapphat()
thì nó sẽ tạo ra một ô nhớ có kiểu dữ liệu giốngxPtr
và thực hiện cấp phát với ô nhớ đó, chứ thực chất ô nhớxPtr
sẽ không thay đổi gì, muốn thay đổi giá trị củaxPtr
thì phải dùng con trỏ hoặc reference tớixPtr
, tức là hàmcapphat()
sửa lại thànhcapphat(int**xPtr, int&n)
hoặccapphat(int* &xPtr, int &n)
.mình tưởng goi hàm truyền con trỏ thì con trỏ nó được thay đổi chứ nhỉ >??? giải thích giúp mình với.
sao hàm nhap voi hàm xuất của t lại không phải chuyền địa chỉ nhỉ >??/ hoi ngu hic.\
cái này là lỗi cơ bản, mình cho bạn 1 ví dụ sai này nè:
Bạn sửa code lại thành:
nôm na là bạn muốn thay đổi giá trị của một vùng nhớ (biến) thông qua hàm thì truyền bằng con trỏ hoặc tham chiếu (reference), muốn thay đổi giá trị chứa trong vùng nhớ kiểu
int
thì dùng một con trỏint*
trỏ tới vùn nhớ đó. tương tự, muốn thay đổi giá trị trong vùng nhớ kiểuint*
thì dùng con trỏint**
, cái khó hiểu ở đây là kiểu dữ liệu mà vùng nhớ đó chứa thôi, nên Gió mới nói là coiint*
là một kiểu dữ liệu. Hoặc bạn dùngtypedef
để định nghĩa lại kiểuint*
thành một kiểu tên khác để dễ hiểumoi người cho t hỏi. t cấp phát bên ngoài rồi , bên trong mà cấp phát lại thì chì cần chuyền con trỏ.
thế thì không cần chuyền địa chỉ con trỏ. tại sao nhỉ
Lỗi này nhiều bạn mới học hay gặp phải. Mình giải thích rõ 1 tí nhé
Tại hàm Main(), bạn tạo 1 con trỏ xPtr và nó không trỏ vào đâu cả.
Bạn gọi hàm capphat(xPtr, n) thì 1 con trỏ mới được tạo ra trong vùng nhớ stack, tạm goi là P’. Con trỏ P’copy nội dụng từ con trỏ xPtr mà bạn truyền vào nên P’ cũng không trỏ vào đâu cả.
Bạn xin cấp phát 1 vùng nhớ động và gán địa chỉ đầu tiên của vùng nhớ cho con trỏ P’. Con trỏ xPtr vẫn chưa trỏ vào đâu cả.
Khi thoát khỏi hàm capphat(), con trỏ P’ bị xóa. Bộ nhớ của bạn bị rò, hay bị leak memory đó.
Tiếp theo bạn yêu cầu nhập dữ liệu vào. Tuy nhiên con trỏ xPtr chưa trỏ vào đâu cả . Runtime sẽ có lỗi segment fault đó.
Sai lầm ở đây là bạn cấp phát bộ nhớ cho 1 con trỏ khác(P’) trong khi bạn vẫn nghĩ là đang dùng xPtr.
Cách khắc phục thì các bạn trên kia đã giải thích, mình k nhắc lại nữa.
Bạn nên markdown code lại cho mọi người dễ theo dõi nha.
sau dòng này, xPtr (giả sử có địa chỉ là 0x111111) trỏ tới ô nhớ đầu tiên của một vùng nhớ nằm trên Heap, giả sử địa chỉ này là 0x123456, lưu ý là địa chỉ này là của phần tử đầu tiên của mảng cấp phát được, địa chỉ của phần tử tiếp theo của mảng sẽ là 0x123456+4
sau khi khai báo hàm
capphat()
compiler sẽ tạo ra một biến làxPtr
giống hệt biếnxPtr
trong hàm main() (giả sử biến này có địa chỉ là 0x222222) nhưng không phải là biến xPtr trongmain()
(địa chỉ là 0x111111) tạm gọi làcopyxPtr
cho dễ phân biệt cảcopyxPtr
vàxPtr
đều trỏ tới cùng 1 địa chỉ 0x123456.Bây giờ sẽ xét trong thân hàm
capphat()
hàm
realloc()
sẽ thay đổi kích thước vùng nhớ được trỏ tới bởicopyxPtr
. Tức là lúc này vùng nhớ mà bắt đầu bằng 0x123456 sẽ có kích thước làn
chứ không phải là 2.Trở lại hàm main(), sau khi gọi
capphat()
thì vùng nhớ 0x123456 trên Heap sẽ không còn là 2 như ban đầu mà là n phần tử, biếnxPtr
trong cấp phát thì bị hủy.NhưngxPtr
vẫn trỏ tới vùng nhớ bắt đầu bằng ô nhớ 0x123456 nên ở dưới sẽ truy xuất vùng nhớ này bằng xPtr một cách bình thường.cảm ơn bạn nhiều , hì . bạn nói chi tiết quá. mong được bạn giúp nhiều hơn