2010-02-28 57 views
5

chức năng của tôi:trong C: Tại sao cấu trúc phân bổ ngăn xếp tồn tại bên ngoài hàm?

struct hostent * gethost(char * hostname){ 
    if(/*some condition under which I want 
     to change the mode of my program to not take a host*/){ 
     return null 
    } 
    else{ 
     struct hostent * host = gethostbyname(hostname); 
     return host; 
    } 
} 

trong chính:

struct hostent * host = gethost(argv[2]); 

(bỏ qua bất kỳ lỗi nhỏ trong các mã, tôi phun từ bộ nhớ)

này hoạt động tốt. và Valgrind không nói với tôi rằng tôi đang mất trí nhớ, mặc dù thực tế tôi không giải phóng.

Tại sao? Tôi nghĩ rằng công cụ được phân bổ trên ngăn xếp biến mất với các cuộc gọi chức năng trở về? hay là vì tôi trả lại con trỏ? điều này có nguy hiểm không?

Trả lời

10

host không được cấp phát trên ngăn xếp, chỉ một con trỏ đến nó nằm trên ngăn xếp. Con trỏ được sao chép khi hàm trả về, vì vậy không có gì sai với mã.

Lưu ý rằng gethostbyname không thực sự phân bổ bộ nhớ động. Nó luôn trả về một con trỏ tới cùng một khối được cấp phát tĩnh, đó là lý do tại sao valgrind không báo cáo một sự rò rỉ. Tuy nhiên, hãy cẩn thận, vì điều đó có nghĩa là bạn phải sao chép hostent được trả về bởi chức năng của bạn nếu bạn muốn lưu lại giá trị cho sau này bởi vì các cuộc gọi khác tới gethost sẽ ghi đè lên nó.

+0

Ah cảm ơn rất nhiều. Vì vậy, nó duy nhất cho 'gethostbyname'? nếu tôi đã làm điều này cho một 'char *', ví dụ, các giá trị trong mảng đó có thể được ghi đè sau này? Chương trình của tôi chỉ phải xử lý một máy chủ cho mỗi lần chạy, vì vậy điều này sẽ ổn. –

+0

Cho dù giá trị được trỏ đến bởi một con trỏ sẽ bị ghi đè lên các cuộc gọi sau sẽ phụ thuộc vào chức năng bạn đang gọi hay không. Đối với bất kỳ hàm thư viện chuẩn C nào trả về một con trỏ mà bạn không truyền vào, bạn có thể giả định nó trả về một con trỏ tới bộ nhớ tĩnh và nó có thể bị ghi đè. – Gabe

0

Vâng bộ nhớ không bị rò rỉ cho đến khi tất cả các tham chiếu đến nó bị mất, trong ví dụ của bạn con trỏ được trả về để vẫn còn một tham chiếu đến nó.

Tuy nhiên, đó là một quyết định thiết kế tồi tệ trong hầu hết các trường hợp dựa vào một phần khác của mã để giải phóng bộ nhớ động. Nếu hàm cần trả về một cấu trúc, ví dụ, người gọi nên làm điều đó và chuyển một con trỏ tới cấu trúc.

+2

Bộ nhớ không bị rò rỉ vì 'gethostbyname' không phân bổ động. Nó trả về một con trỏ tĩnh mỗi lần. – Gabe

+2

Và ai cầu nguyện, hãy theo dõi các tham chiếu trên con trỏ này?:) – vladr

+2

Không ai theo dõi tham chiếu đến con trỏ. Khối bộ nhớ được cấp phát khi thư viện socket tải và không được deallocated cho đến khi quá trình kết thúc hoặc thư viện socket được unloaded. – Gabe

2

từ hướng dẫn:

RETURN VALUE 
     The gethostbyname() and gethostbyaddr() functions return the hostent 
     structure or a NULL pointer if an error occurs. On error, the h_errno 
     variable holds an error number. When non-NULL, the return value may 
     point at static data, ... 

Một số bộ nhớ được dành riêng tại thời gian biên dịch (tức là bên trong nhị phân mã.) Cho cấu trúc, hàm trả về một con trỏ tới bộ nhớ này.

3

Nó tốt và không bị rò rỉ vì con trỏ trả về không trỏ đến dữ liệu trên ngăn xếp hoặc đống, nhưng một số biến tĩnh.

http://linux.die.net/man/3/gethostbyname:

Các chức năng GetHostByName() và gethostbyaddr() có thể trở lại con trỏ đến dữ liệu tĩnh, có thể được ghi đè bởi sau đó gọi. Sao chép cấu trúc hostent không đủ, vì nó chứa con trỏ; một bản sao sâu là bắt buộc.

+0

Tại sao "toàn cầu"? Toàn cầu và tĩnh không giống nhau. – Ben

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