2012-03-20 10 views
5

Kiedy wywołuję NSLog z C++, Xcode skarży się, że ciąg znaków przekazany do NSLog nie jest dosłownym łańcuchem znaków. Oto linia kodu, który wyzwala ostrzeżenie:Wywołanie NSLog z C++: "Ciąg formatu nie jest literałem łańcuchowym (potencjalnie niepewnym)"

NSLog(CFSTR("Leaking?")); 

nie jestem świadomy jakikolwiek sposób kodować dosłownego NSString w C++, a nie widzę odpowiedniego ostrzeżenia można wyłączyć w ustawieniach projektu . Czy istnieje sposób wywołania NSLog z C++ bez wywoływania tej wiadomości? Używam Xcode 4.2.1.

Edytuj: To naprawdę jest kod C++. Zazwyczaj unikam Objective-C++, przylegając do Clucji Objective-C lub zwykłego C++, ponieważ nie ma oficjalnej dokumentacji na temat tego, co działa w Objective-C++, a co nie. Znalazłem tylko niejasne ostrzeżenia, że ​​(na przykład) mogą wystąpić problemy z niektórymi częściami STL. Używam szablonów, STL i innych "zaawansowanych" funkcji C++, więc chcę je bezpiecznie odtworzyć.

Edytuj # 2, rozwiązanie: Po prostu zorientowałem się, że klang obsługuje o wiele więcej flag ostrzegawczych niż faktycznie udokumentowanych. (Powinno to być oczywiste z długiej listy ostrzeżeń, które zaoferował mi Xcode.) Próbowałem -Wno-format-nonliteral a la gcc, a teraz Xcode jest szczęśliwy.

+2

Jeśli dzwonisz 'NSLog', który jest częścią Foundation, to używasz Objective-C. Użyj '@" Leaking? "I upewnij się, że twój plik ma rozszerzenie' .mm'. – Joe

+0

@Joe ... chyba że ma na myśli Objective-C++? – csl

+1

@csl Przenieśliłem komentarz do odpowiedzi z pewnym wyjaśnieniem. – Joe

Odpowiedz

7

Wszystko, co musisz zrobić, to napisać @"this", aby utworzyć dosłowny obiekt NSString.

Wymień tę linię na NSLog(@"Leaking?");, a wszystko powinno być w porządku.

Być może trzeba będzie zmienić nazwę pliku z rozszerzeniem .mm, aby upewnić się, że jest on skompilowany jako Objective-C++ (zmutowane dziecko-miłość Objective-C i C++). Jeśli nie chcesz tego zrobić, możesz utworzyć funkcję wrapper w małym pliku mm, który wywoła NSLog, a następnie wywołaj tę funkcję z twojego kodu C++. to będzie wyglądać następująco:

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

uwaga, że ​​powodem kompilator daje Ci żal jest, że za pomocą czegokolwiek, ale niezmiennej ciąg dosłownym (gdzie zawartość jest znany w czasie kompilacji) to zagrożenie bezpieczeństwa. W przeciwnym razie można zmienić ciąg formatu, aby uwzględnić specyfikatory formatu (np. %d) dla parametrów, których nie ma. Gdyby tak się stało, NSLog otrzymywałby losowe wskaźniki ze stosu i mogło się zdarzyć coś złego. (Aby uzyskać więcej informacji, zobacz: this question).

+0

+1 dla zaktualizowanej odpowiedzi. – Joe

+0

+1 za sugestię zdefiniowania funkcji pomocnika w oddzielnym pliku .mm. Tym razem go nie użyłem, ale jestem pewien, że przyda się w przyszłości, ponieważ jestem ogólnie ostrożny przy używaniu Objective-C++. – dkh

4

Jeśli dzwonisz pod numer NSLog, który jest częścią Foundation, to używasz Objective-C. Użyj numeru NSLog(@"Leaking?"); i upewnij się, że plik ma rozszerzenie .mm, aby było jasne, że miksujesz Objective-C i C++.

+0

Aby wyjaśnić, jestem zdezorientowany. Dlaczego nie nazwać tego rozszerzenia '.m' zamiast' .mm', jeśli Foundation jest Objective-C? Czy chciałeś powiedzieć, że NSLog jest zamiast tego Objective C++, czy jestem zdezorientowany? Dzięki! – jmort253

+1

Spekulowałem, że może 'NSLog' został wywołany z pliku' .cpp', który nie działałby, ponieważ 'NSLog' jest tylko' Objective-C'. I mieszać 'Objective-C' i' C++ 'rozszerzenie [powinno być' .mm'] (http://stackoverflow.com/questions/7727249/calling-c-function-from-objective-c-class/7727308 # 7727308). – Joe

Powiązane problemy