2012-01-01 24 views
30

Tôi đang chơi với tệp time.h trong C giúp chúng tôi có chức năng thời gian/ngày.Cấu trúc kết quả của thời gian cục bộ được phân bổ trong C là bao nhiêu?

Tôi đã xem qua:

struct tm * _Cdecl localtime(const time_t *__timer); 

... mà dường như trở về một con trỏ đến struct tm. Tôi đã tìm thấy rằng trở lại theo địa chỉ chủ yếu được sử dụng để trả lại cấp phát bộ nhớ mới.

Nếu đúng như vậy, lợi tức trên thực tế hoạt động như thế nào (địa chỉ trả lại của struct tm). Đối tượng trả về có được định nghĩa ở đâu đó không?

Cảm ơn

+0

Bạn xác định và phân bổ cấu trúc tm *** trong mã của bạn. *** localtime() lưu trữ kết quả của nó trong cấu trúc đó và trả về một con trỏ tới cùng cấu trúc đó. Điều này có thể có vẻ dư thừa nhưng nó tiện dụng vào các thời điểm để có được con trỏ trở lại, mặc dù bạn biết nơi struct là. –

+3

@PeteWilson - Um, không, bạn không biết. Vui lòng xem câu trả lời bên dưới. Những gì bạn mô tả chỉ là trường hợp trong phiên bản '_r' của cuộc gọi (' localtime_r() ') từ SUSv2 hoặc phiên bản' _s' của cuộc gọi trong MSVC –

+0

có thể trùng lặp của [Không trả về struct của localtime() cần phải được giải phóng?] (http://stackoverflow.com/questions/6210880/does-returned-struct-of-localtime-need-to-be-freed) –

Trả lời

37

Con trỏ trả về bởi localtime (và một số chức năng khác) đang thực sự con trỏ để tĩnh phân bổ bộ nhớ. Vì vậy, bạn không cần phải giải phóng. Hơn nữa, bạn không nên giải phóng nó.

http://www.cplusplus.com/reference/clibrary/ctime/localtime/

Cấu trúc này được tĩnh được phân bổ và được chia sẻ bởi các chức năng gmtime và localtime. Mỗi lần một trong hai chức năng này là được gọi là nội dung của cấu trúc này bị ghi đè.

EDIT: Thêm một vài điều được đề cập trong nhận xét.

Kết quả trực tiếp của cấu trúc dữ liệu được chia sẻ này là localtime và các chức năng tương tự không an toàn chỉ. Giải pháp an toàn chủ đề thay đổi theo các nền tảng khác nhau. localtime_r for POSIXlocaltime_s for MSVC.

+1

+1. Đó là khó chịu mà C (99) tiêu chuẩn nói gì về điều này, mặc dù ... –

+5

@OliCharlesworth thực sự nó có, đọc (C99, 7.23.3 Chức năng chuyển đổi thời gian) "Ngoại trừ chức năng strftime, các chức năng này mỗi trở lại một con trỏ đến một trong hai loại đối tượng tĩnh [...] Thực hiện bất kỳ hàm nào trả về một con trỏ tới một trong các kiểu đối tượng này có thể ghi đè lên thông tin trong bất kỳ đối tượng nào cùng loại được trỏ đến bởi giá trị được trả về từ bất kỳ lệnh gọi trước nào đến bất kỳ cái nào trong số đó. " – ouah

+1

Cũng có thể là tốt để chỉ ra rằng vì điều này, nó không phải là threadsafe và các phiên bản '_r' của các cuộc gọi này là. –

3

Thực tế, localtime thường trả về địa chỉ của đối tượng tĩnh. Tôi nghi ngờ nó trông như thế này:

struct tm * 
localtime(const time_t *timer) 
{ 
    static struct tm tm; 

    /* Magic. */ 

    return &tm; 
} 
+0

Bạn đang thiếu một '&' Tôi tin rằng – ChrisWue

+1

@ChrisWue bk1e đã được chỉnh sửa :-) – cnicutar

+0

Không có đối tượng nào trong C :) –

11

Nó trả về một con trỏ đến một mảnh bộ nhớ tĩnh được phân bổ (có thể hoặc là một biến static định nghĩa bên localtime hoặc toàn cầu được xác định ở đâu đó trong thư viện runtime C). Bạn không được miễn phí bộ nhớ đó.

Rõ ràng chức năng này không phải là reentrant (nhưng có thể được thread-an toàn nếu TLS được sử dụng).

Bạn phải cẩn thận khi sử dụng con trỏ này: không bao giờ thực hiện bất kỳ cuộc gọi chức năng mà có thể gọi localtime/gmtime/... trước khi bạn đã hoàn thành sử dụng con trỏ đó, nếu không thì nội dung của bộ nhớ được tham chiếu bởi con trỏ của bạn có thể thay đổi (trong phản ứng với cuộc gọi mới tới localtime) và bạn sẽ được đọc các giá trị liên quan đến một số khác time_t.

Nói chung, thiết kế của thư viện ngày/giờ khá lạc hậu, kiểu tối ưu này đáng giá khi ngôn ngữ C được thiết kế, ngày nay nó chỉ gây ra vấn đề.

Để giải quyết những vấn đề này có ít nhất hai phiên bản khác nhau cải thiện các chức năng: localtime_r (SUSv2, r ở lại cho "lõm") và localtime_s (Microsoft, s ở lại cho "an toàn").Thực tế đáng buồn cho tính di động là chúng gần như giống nhau (chúng yêu cầu đích struct tm được chuyển thành tham số), nhưng khác nhau về tên và thứ tự của các tham số.

+0

Ghi chú: 'localtime_s()' cũng được mô tả chi tiết trong thông số C11: phần quy định K.3.8.2.4. Không chắc chắn nếu MS (hoặc bất kỳ ai) đáp ứng đặc điểm kỹ thuật C11 đó. – chux

5

Các man page nói:

điểm Giá trị trả về một struct tĩnh được phân bổ mà có thể được ghi đè bởi các cuộc gọi tiếp theo với bất kỳ hàm ngày tháng và thời gian.

Ngoài ra:

Các localtime_r() chức năng không giống nhau, nhưng lưu trữ các dữ liệu trong một cấu trúc do người dùng cung cấp. Nó không cần đặt tzname, múi giờ và ánh sáng ban ngày.

0

Đối tượng nhọn được trả về bởi hàm localtime có thời lượng lưu trữ tĩnh.

3

Chúng trả về con trỏ tới cấu trúc tĩnh cục bộ cho thư viện. Từ trang người đàn ông:

NOTES 

The four functions asctime(), ctime(), gmtime() and localtime() return 
a pointer to static data and hence are not thread-safe. Thread-safe 
versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are spec‐ 
ified by SUSv2, and available since libc 5.2.5. 

POSIX.1-2001 says: "The asctime(), ctime(), gmtime(), and localtime() 
functions shall return values in one of two static objects: a broken- 
down time structure and an array of type char. Execution of any of the 
functions may overwrite the information returned in either of these 
objects by any of the other functions." This can occur in the glibc 
implementation.
+0

+ 1-ing này để đề cập đến các phiên bản an toàn thread. – Mysticial

+0

trang người đàn ông là một điều tuyệt vời. Vào thời điểm đó, SO đã không cho tôi thấy rằng bất kỳ ai khác đã trả lời vì vậy tôi đã tìm ra rằng tôi chỉ đăng các tài liệu liên quan. –

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