2012-03-20 10 views
5

Cuando llamo a NSLog desde C++, Xcode se queja de que la cadena de formato pasada a NSLog no es una cadena literal. Aquí hay una línea de código que activa el aviso:Llamar a NSLog desde C++: "Cadena de formato no es una cadena literal (potencialmente insegura)"

NSLog(CFSTR("Leaking?")); 

No estoy al tanto de cualquier manera de codificar un NSString literal en C++, y no veo una advertencia relevante puedo desactivar en la configuración del proyecto . ¿Hay alguna manera de llamar a NSLog desde C++ sin activar este mensaje? Estoy usando Xcode 4.2.1.

Editar: Esto realmente es código C++. Por lo general, evito Objective-C++, apegándome a Objective-C o simplemente a C++, porque no hay documentación oficial sobre lo que funciona en Objective-C++ y lo que no. Solo he encontrado advertencias vagas de que (por ejemplo) puede haber problemas con algunas partes de la STL. Yo uso plantillas, el STL y otras características "avanzadas" de C++, así que quiero ir a lo seguro.

Editar # 2, la solución: Acabo de descubrir que el clang admite muchas más banderas de advertencia de las que en realidad están documentadas. (Debería haber sido obvio de la larga lista de advertencias que Xcode me ofreció.) Intenté -Wno-format-nonliteral a la gcc, y ahora Xcode está contento.

+2

Si está llamando 'NSLog', que es parte de Foundation, entonces está usando Objective-C. Use '@" Leaking? "' Y asegúrese de que su archivo tenga la extensión '.mm'. – Joe

+0

@Joe ... a menos que se refiera a Objective-C++? – csl

+1

@csl Moví el comentario a una respuesta con alguna aclaración. – Joe

Respuesta

7

Todo lo que tienes que hacer es escribir @"this" para crear un objeto NSString literal.

Reemplace esa línea con NSLog(@"Leaking?"); y debería estar bien.

Puede que tenga que cambiar el nombre de su archivo con la extensión .mm para asegurarse de que se compila como Objective-C++ (el amor-hijo mutante de Objective-C y C++). Si no quiere hacer eso, podría hacer una función de contenedor en un pequeño archivo mm que llame a NSLog, y luego llamar a esa función desde su código C++. Se vería así:

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

Tenga en cuenta que la razón por la que el compilador te da pena es que el uso de cualquier cosa menos una cadena literal inmutable (donde los contenidos son conocidos en tiempo de compilación) es un riesgo de seguridad. De lo contrario, la cadena de formato se podría cambiar para incluir los especificadores de formato (por ejemplo, %d) para los parámetros que no están allí. Si eso sucediera, NSLog obtendría punteros aleatorios de la pila y podría ocurrir algo malo. (Consulte this question para obtener más información.)

+0

+1 para la respuesta actualizada. – Joe

+0

+1 para la sugerencia de definir una función auxiliar en un archivo .mm separado. No lo usé esta vez, pero estoy seguro de que será útil en el futuro, ya que generalmente soy cauteloso sobre el uso de Objective-C++. – dkh

4

Si llama al NSLog, que es parte de Foundation, entonces está utilizando Objective-C. Use NSLog(@"Leaking?"); y asegúrese de que su archivo tenga una extensión .mm para dejar en claro que está mezclando Objective-C y C++.

+0

Solo para aclarar, estoy confundido. ¿Por qué no simplemente nombrar esto como una extensión '.m' en lugar de' .mm', si Foundation es Objective-C? ¿Quiso decir que NSLog es Objective C++ en su lugar, o estoy confundido? ¡Gracias! – jmort253

+1

Estaba especulando que tal vez 'NSLog' recibiera llamadas de un archivo' .cpp' que no funcionaría porque 'NSLog' solo es' Objective-C'. Y para mezclar 'Objective-C' y' C++ 'la extensión [debería ser' .mm'] (http://stackoverflow.com/questions/7727249/calling-c-function-from-objective-c-class/7727308 # 7727308). – Joe

Cuestiones relacionadas