2013-03-15 47 views
5

Có phải an toàn là static const trong chuỗi lớp học không? Trong mã bên dưới, tôi có trailingBytesForUTF8 là một mảng ký tự static const. Có thể có nhiều luồng có thể hiện đối tượng riêng của chúng trong lớp CConvertUTF. Sẽ có bất kỳ vấn đề trạng thái có thể thay đổi nào khi nhiều luồng truy cập cùng một mảng trailingBytesForUTF8 cùng một lúc hay bất kỳ vấn đề luồng nào khác không? Cũng lưu ý rằng các chuỗi sẽ không bao giờ chia sẻ cùng một cá thể đối tượng của lớp CConvertUTF.static const char [] trong chủ đề lớp an toàn?

// .h 
class CConvertUTF final 
{ 
    private: 
     static const char trailingBytesForUTF8[256]; 
    public: 
     bool IsLegalUTF8Sequence(const char *source, const char *sourceEnd); 
     bool IsLegalUTF8(const char *source, int length); 
}; 

// .cpp 
const char CConvertUTF::trailingBytesForUTF8[256] = { 
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 
    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 
}; 

bool CConvertUTF::IsLegalUTF8Sequence(const char *source, const char *sourceEnd) { 
    int length = trailingBytesForUTF8[*source]+1; 
    if (source+length > sourceEnd) { 
    return false; 
    } 
    return IsLegalUTF8(source, length); 
} 

bool CConvertUTF::IsLegalUTF8(const char *source, int length) { 
    char a; 
    const *char = source+length; 
    switch (length) { 
    default: return false; 
    /* Everything else falls through when "true"... */ 
    case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; 
    case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; 
    case 2: if ((a = (*--srcptr)) > 0xBF) return false; 

    switch (*source) { 
     /* no fall-through in this inner switch */ 
     case 0xE0: if (a < 0xA0) return false; break; 
     case 0xED: if (a > 0x9F) return false; break; 
     case 0xF0: if (a < 0x90) return false; break; 
     case 0xF4: if (a > 0x8F) return false; break; 
     default: if (a < 0x80) return false; 
    } 

    case 1: if (*source >= 0x80 && *source < 0xC2) return false; 
    } 
    if (*source > 0xF4) return false; 
    return true; 
} 
+0

(Hmm Với 'const kiểm tra char [] = {0xA, 0xFF, 0xA};. IsLegalUTF8Sequence (kiểm tra, thử nghiệm + 3) ' là 'true'.) – aschepler

+0

@aschepler Cảm ơn bạn đã gỡ lỗi, mã là mã nguồn mở cũ từ Unicode Inc. mà tôi vừa thêm một kiểu lập trình hướng đối tượng vào. –

Trả lời

7

Biến chỉ đọc (const) luôn an toàn cho đến khi chúng bị hủy. Kể từ khi một đối tượng tĩnh chỉ bị phá hủy khi chấm dứt chương trình, chúng là tốt cho cuộc sống của chương trình.

Ngoại lệ duy nhất sẽ là đối tượng có thành viên mutable, nhưng điều đó không áp dụng cho mảng char.

+0

Ví dụ của người gửi là (có thể) thread-safe vì nó (có thể) được khởi tạo trước khi bất kỳ chủ đề mới được tạo ra, nhưng các biến không đáng tin cậy thread-safe mà không có khóa mutex, ngay cả khi chúng có const hoặc thậm chí là const tĩnh trước mặt chúng, ngay cả khi chúng xuất hiện trong không gian toàn cầu (vì bạn không có quyền kiểm soát trật tự vô sinh). Tôi nghĩ rằng đây là cố định trong C + + 11. – Scott

+1

@Scott Tôi dựa trên câu trả lời của tôi trên giả định rằng các biến đó sẽ được khởi tạo * trước * bất kỳ chuỗi thay thế nào có thể được bắt đầu. Trong hindsight nó có thể là một khởi tạo tĩnh có thể bắt đầu một sợi, hoặc một biến tĩnh có thể ở cấp khối (bên trong một chức năng) chứ không phải là cấp lớp. Đối với các loại POD const tĩnh, nó không tạo ra sự khác biệt nào, bởi vì phương thức phổ quát của việc khởi tạo chúng là đưa nội dung của chúng vào không gian mã được nạp trước khi bắt đầu thực hiện. –

+1

Đồng ý. Tôi không biết nếu tiêu chuẩn đảm bảo điều này, nhưng POD tĩnh là rất có khả năng tồn tại trước khi bất kỳ mã nào được chạy. Lưu ý rằng nếu một con trỏ * không phải là const (chỉ đến dữ liệu const nhưng chính nó là không phải là const) thì con trỏ có thể không được khởi tạo trước khi main(). Tôi chỉ đưa tất cả những điều đó bởi vì gần đây chúng ta có bit bởi một lớp singleton (sử dụng nhiều chủ đề của tôi) với khởi tạo tĩnh lười (ví dụ: C :: instance() {static C instance; return instance;}), hai luồng được sử dụng singleton " lần đầu tiên "và chạy đồng thời hàm tạo - may mắn là lỗi seg đã giúp chúng tôi tìm ra lỗi. – Scott

3

mọi dữ liệu được chỉ định là static const là toàn cầu và chỉ đọc.

Điều này có nghĩa là được bảo vệ khỏi điều kiện chủng tộc vì không ai có thể sửa đổi dữ liệu.

Đối với một điều kiện chủng tộc dữ liệu xuất hiện thì phải có ít nhất là trên hoạt động ghi

+0

Trình biên dịch có thể tạo mã an toàn chỉ để "nói" rằng biến trỏ tới một khối dữ liệu trước khi bất kỳ đối tượng nào khác được khởi tạo, nhưng vì thứ tự khởi tạo không được đảm bảo, có nguy cơ đa luồng thậm chí với "tĩnh const "dữ liệu. Tôi nghĩ rằng đây là cố định trong C + + 11. – Scott