2012-03-20 27 views
5

Khi tôi gọi NSLog từ C++, Xcode than phiền rằng chuỗi định dạng được chuyển tới NSLog không phải là chuỗi ký tự. Dưới đây là một dòng mã kích hoạt cảnh báo:Gọi NSLog từ C++: "Chuỗi định dạng không phải là chuỗi chữ (có khả năng không an toàn)"

NSLog(CFSTR("Leaking?")); 

Tôi không biết cách nào để mã hóa một NSString chữ trong C++, và tôi không thấy một cảnh báo liên quan Tôi có thể tắt trong các thiết lập dự án . Có cách nào để gọi NSLog từ C++ mà không kích hoạt thông điệp này? Tôi đang sử dụng Xcode 4.2.1.

Chỉnh sửa: Đây thực sự là mã C++. Tôi thường tránh Objective-C++, gắn bó với Objective-C hoặc cũ C++, bởi vì không có tài liệu chính thức về những gì làm việc trong Objective-C++ và những gì không. Tôi đã chỉ tìm thấy những cảnh báo mơ hồ rằng (ví dụ) có thể có vấn đề với một số phần của STL. Tôi sử dụng các mẫu, STL và các tính năng "nâng cao" khác của C++, vì vậy tôi muốn chơi nó an toàn.

Chỉnh sửa # 2, giải pháp: Tôi vừa tìm ra clang hỗ trợ nhiều cờ cảnh báo hơn là thực sự được ghi lại. (Nó phải có được rõ ràng từ danh sách dài các cảnh báo mà Xcode cung cấp cho tôi.) Tôi đã thử -Wno-format-nonliteral a la gcc, và bây giờ Xcode là hạnh phúc.

+2

Nếu bạn đang gọi 'NSLog', là một phần của Foundation, thì bạn đang sử dụng Objective-C. Sử dụng '@" Rò rỉ? "' Và đảm bảo tệp của bạn có phần mở rộng '.mm'. – Joe

+0

@Joe ... trừ khi anh ta có nghĩa là Objective-C++? – csl

+1

@csl Tôi đã chuyển nhận xét đến câu trả lời bằng một số giải thích rõ ràng. – Joe

Trả lời

7

Tất cả những gì bạn phải làm là viết @"this" để tạo đối tượng NSString theo nghĩa đen.

Vì vậy hãy thay dòng đó bằng NSLog(@"Leaking?"); và bạn sẽ ổn.

Bạn có thể phải đổi tên tệp của mình bằng tiện ích mở rộng .mm để đảm bảo tệp được biên dịch dưới dạng Mục tiêu-C++ (con yêu thích đột biến của Mục tiêu-C và C++). Nếu bạn không muốn làm điều đó, bạn có thể tạo một hàm bao bọc trong một tệp mm nhỏ gọi NSLog, và sau đó gọi hàm đó từ mã C++ của bạn. Nó sẽ giống như thế này:

void MyNSLog(const char *message) 
{ 
    NSLog(@"%s", message); 
} 

Lưu ý rằng lý do trình biên dịch được đem lại cho bạn đau buồn là sử dụng bất cứ điều gì nhưng một chuỗi bất biến chữ (nơi các nội dung được biết tại thời gian biên dịch) là một nguy cơ bảo mật. Nếu không, chuỗi định dạng có thể được thay đổi để bao gồm các chỉ định định dạng (ví dụ: %d) cho các tham số không có ở đó. Nếu điều đó xảy ra, NSLog sẽ chỉ nhận được các con trỏ ngẫu nhiên từ ngăn xếp và một cái gì đó xấu có thể xảy ra. (Xem this question để biết thêm thông tin.)

+0

+1 cho câu trả lời được cập nhật. – Joe

+0

+1 để đề xuất xác định hàm trợ giúp trong tệp .mm riêng biệt. Tôi không sử dụng nó lần này, nhưng tôi chắc chắn nó sẽ có ích trong tương lai, vì tôi thường thận trọng khi sử dụng Objective-C++. – dkh

4

Nếu bạn đang gọi NSLog, là một phần của Foundation, thì bạn đang sử dụng Objective-C. Sử dụng NSLog(@"Leaking?"); và đảm bảo tệp của bạn có tiện ích mở rộng .mm để làm rõ rằng bạn đang trộn Objective-CC++.

+0

Chỉ cần làm rõ, tôi đang bối rối. Tại sao không chỉ đặt tên này là phần mở rộng '.m' thay vì' .mm', nếu Foundation là Objective-C? Bạn có ý nói rằng NSLog là mục tiêu C++ thay vào đó, hay tôi nhầm lẫn? Cảm ơn! – jmort253

+1

Tôi đã suy đoán rằng có lẽ 'NSLog' đã được gọi từ một tệp' .cpp' không hoạt động vì 'NSLog' chỉ là' Mục tiêu-C'. Và để trộn 'Objective-C' và' C++ 'phần mở rộng [nên là' .mm'] (http://stackoverflow.com/questions/7727249/calling-c-function-from-objective-c-class/7727308 # 7727308). – Joe

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