2008-09-12 22 views
371

así que estoy trabajando en una base de código excesivamente grande, y recientemente actualizado a gcc 4.3, que ahora activa esta advertencia:¿Cómo deshacerse de la conversión obsoleta de la constante de cadena a las advertencias de 'char *' `en GCC?

advertencia: desaprobado conversión de cadena constante a 'char *'

obviamente, la forma correcta de solucionar este problema es encontrar cada declaración como

char *s = "constant string"; 

o llamada de función como:

void foo(char *s); 
foo("constant string"); 

y hacerlos const char punteros. Sin embargo, eso significaría tocar 564 archivos, como mínimo, lo cual no es una tarea que desee realizar en este momento. El problema ahora mismo es que me estoy ejecutando con -werror, así que necesito alguna manera de reprimir estas advertencias. ¿Cómo puedo hacer eso?

+0

Cuando llegas a hacer frente al reemplazo de 554 líneas, sed es un buen amigo. Asegúrate de hacer una copia de seguridad primero. – Matt

+0

Miré las discusiones sobre cómo suprimir los mensajes de error y cuáles deberían ser los reemplazos correctos. No tengo ninguna opinión sobre eso. Sin embargo, creo que Matt está en el camino correcto. Defina lo que quiere reemplazar por qué. Solo necesitas las expresiones regulares correctas. Haga los cambios en una copia. Use "diff" para compararlos con el original. Hacer los cambios usando sed es rápido, fácil y gratis, y diff también es rápido, fácil y gratis. Pruébelo y vea cuántos cambios debe revisar. Publique lo que desea reemplazar por qué, y permita que los usuarios sugieran reemplazos de expresiones regulares. –

Respuesta

211

creo que pasa a -Wno-write-strings gcc suprimir esta advertencia.

+6

Se puede desactivar en cada archivo básico usando pragmas. –

+16

@PriyankBolia bdonlan comentó la respuesta de Rob Walker que puede utilizar el '#pragma Diagnóstico de GCC ignorado" -Wwrite-strings "'. – MasterMastic

+9

Excepto si controla la API, en cuyo caso la respuesta de @ John a continuación, sobre cómo cambiar la firma para aceptar const char *, es más correcta. – jcwenger

29

Si se trata de una base de código activo, es posible que aún desee actualizar la base de código. Por supuesto, realizar los cambios manualmente no es factible, pero creo que este problema podría resolverse de una vez por todas con un único comando sed. No lo he probado, así que tome lo siguiente con un grano de sal.

find . -exec sed -E -i .backup -n \ 
    -e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \; 

Esto podría no encontrar todos los lugares (incluso sin considerar las llamadas de función), pero podría aliviar el problema y hacer posible la realización de los pocos cambios restantes manualmente.

+6

que solo resuelve advertencias de declaraciones y no llamadas de función +1 para sed fu de todos modos: p –

0

El problema ahora es que estoy corriendo con -Werror

Este es el verdadero problema, la OMI. Puede probar algunas formas automáticas de pasar de (char *) a (const char *) pero les pondré dinero, no solo trabajando. Tendrás que involucrar a un ser humano para al menos parte del trabajo. A corto plazo, simplemente ignore la advertencia (pero IMO la deja encendida, o nunca se arreglará) y simplemente elimine el -Werror.

+8

La razón por la que la gente usa -Werror es para que las advertencias * do * get fijo. De lo contrario, nunca se arreglan. –

+2

La razón por la que las personas usan -Werror es porque solo han trabajado en proyectos de juguetes, o son masoquistas. Tener su código no se puede construir debido a una actualización de GCC es un problema real cuando tiene 100k + LOC. Dito. alguien agregando basura como "-Wno-write-strings" a la compilación para deshacerse de las advertencias molestas (como sugiere el comentario mejor calificado en esta publicación). –

+2

hay un claro desacuerdo en ese tema, por ejemplo http://programmer.97things.oreilly.com/wiki/index.php/Keep_the_Build_Clean –

1

¿Por qué no se utiliza la opción -Wno-deprecated hacer caso omiso de los mensajes de advertencia en desuso?

63

tuve un problema similar, he resuelto de esta manera:

#include <string.h> 

extern void foo(char* m); 

int main() { 
    // warning: deprecated conversion from string constant to ‘char*’ 
    //foo("Hello"); 

    // no more warning 
    char msg[] = "Hello"; 
    foo(msg); 
} 

¿Es esta una forma adecuada de resolver esto? No tengo acceso a foo para adaptarla a aceptar const char*, aunque eso sería una mejor solución (porque no cambia foom).

+8

@elcuco, ¿qué propones? No pude editar foo e intenté encontrar una solución que no requiriera la supresión de la advertencia. En mi caso, este último era más una cuestión de ejercicio, pero para el cartel original parecía importante. Por lo que puedo decir, mi respuesta es la única que resolvería las condiciones de mi y de la OP al mismo tiempo, por lo que podría ser una respuesta valiosa para alguien. Si cree que mi solución no es lo suficientemente buena, ¿podría proporcionarme una alternativa? (Eso no incluye editar foo o ignorar la advertencia). – BlackShift

+0

si suponemos que foo está codificado correctamente (lo que desafortunadamente no parece ser el caso para el código del que habla Josh Matthews) esta es la mejor solución. eso es porque si la función necesita cambiar realmente la cadena 'msg' pasándola, una cadena constante rompería el código, ¿verdad? pero de todos modos esto no parece responder a la pregunta porque los errores ya están en el código anterior, no en el nuevo, por lo que tendría que cambiar el código anterior de todos modos. –

+0

Ese es el enfoque que tomé también. Y si alguien está buscando esto para los casos de 'char **' en 'PyArg_ParseTupleAndKeywords' hago algo como esto:' static char kw [] [16] = {"mode", "name", "ip", "port "}; static char * kwlist [] = {kw [0], kw [1], kw [2], kw [3], NULL}; ' – dashesy

2

También puede crear una cadena de escritura desde una constante llamando strdup() cadena.

Por ejemplo, este código genera una advertencia:

putenv("DEBUG=1"); 

Sin embargo, el siguiente código no (se hace una copia de la cadena en el montón antes de pasarla a putenv):

putenv(strdup("DEBUG=1")); 

En este caso (y quizás en la mayoría de los demás) apagar la advertencia es una mala idea, está ahí por una razón. La otra alternativa (hacer que todas las cadenas sean editables por defecto) es potencialmente ineficiente.

¡Escucha lo que el compilador te está diciendo!

+2

Y también pierde la memoria asignada para esa cadena editable. – RBerteig

+1

Sí lo hace, eso es a propósito. No es un problema con el código de una sola vez (por ejemplo, inicialización), como se indicó anteriormente. O bien, puede administrar la memoria usted mismo y liberarla cuando haya terminado con ella. – BillAtHRST

+1

Esto es un consejo horrible: imagine que alguien copia este código en un bucle ... – Ghostrider

24

No puedo usar el interruptor del compilador. Así que me he convertido esta:

char *setf = tigetstr("setf"); 

a esto:

char *setf = tigetstr((char *)"setf"); 
+1

+1 - no puede cambiar lvalor de las aplicaciones, solo rvalue. esto probó arreglar el problema real. otros simplemente solucionan algunos problemas con el compilador. – elcuco

+1

Lo que es realmente molesto es que tigetstr() debería ser un prototipo con un (const char *), no un (char *) – vy32

+2

Cuando hago esto, aparece "warning: cast from type 'const char *' to type ' char * 'arroja la constness' en su lugar. Tuve que usar un const_cast para deshacerme de todas las advertencias: const_cast ("setf") – CrouZ

7

Test string es const string. Así se puede resolver de esta manera:

char str[] = "Test string"; 

o:

const char* str = "Test string"; 
printf(str); 
1

ver esta situación:

typedef struct tagPyTypeObject 
{ 
    PyObject_HEAD; 
    char *name; 
    PrintFun print; 
    AddFun add; 
    HashFun hash; 
} PyTypeObject; 

PyTypeObject PyDict_Type= 
{ 
    PyObject_HEAD_INIT(&PyType_Type), 
    "dict", 
    dict_print, 
    0, 
    0 
}; 

ver el campo de nombre, en gcc que compile sin previo aviso, pero en g ++ se lo haré, no sé por qué.

+0

gcc implica tratar el archivo como archivo fuente C, g ++ tratarlo como archivo fuente C++, a menos que se anule por -x ?? opción. Entonces, un lenguaje diferente, c y C++ tiene sutiles diferencias sobre lo que debería ser una advertencia. – zhaorufei

5

¿Por qué no usar simplemente el tipo de fundición?

(char*) "test" 
23

Aquí se explica cómo hacerlo en línea en un archivo, para que no tenga que modificar su archivo Makefile.

// gets rid of annoying "deprecated conversion from string constant blah blah" warning 
#pragma GCC diagnostic ignored "-Wwrite-strings" 

Más tarde puede ...

#pragma GCC diagnostic pop 
-1
PyTypeObject PyDict_Type= 
{ ... 

PyTypeObject PyDict_Type= 
{ 
    PyObject_HEAD_INIT(&PyType_Type), 
        "dict", 
        dict_print, 
        0, 
        0 
}; 

ver el campo de nombre, en gcc que compile sin previo aviso, pero en g ++ Será, yo no sé por qué.

en gcc (Compiling C), -Wno-write-strings está activo de forma predeterminada.

en g++ (Compiling C++) -Wwrite-secuencias se activa por defecto

Es por esto que hay un comportamiento diferente. Para nosotros el uso de macros de Boost_python genera tales advertencias. por lo que utilizar -Wno-write-strings al compilar C++ ya que siempre usamos -Werror

0

sólo tiene que utilizar la opción -w de g ++

ejemplo:

g ++ -o -w simple.o sencilla.cpp -lpthread

Recuerde que esto no evita la depreciación sino que evita que se muestre un mensaje de advertencia en el terminal.

Ahora si realmente quieren evitar el uso de palabras clave const desaprobación de esta manera:

const char* s="constant string"; 
507

Cualquier función en la que se pasan los literales de cadena "I am a string literal" deben utilizar char const * como el tipo de lugar de char*.

Si va a arreglar algo, corríjalo bien.

Explicación:

No se puede utilizar literales de cadena para inicializar cadenas que se van a modificar, debido a que son de tipo const char*. La eliminación de la constness para modificarlos más tarde es undefined behaviour, por lo que debe copiar sus cadenas const char*char por char en cadenas char* asignadas dinámicamente para modificarlas.

Ejemplo:

#include<iostream> 
using namespace std; 
void print(char *); 
void print(const char *ch) 
{ 
    cout<<ch; 
} 

    int main(){ 
     print("Hello"); 
     return 0; 
    } 
+21

Si bien esto es cierto, no siempre tienes control sobre las API de terceros que pueden no usar correctamente 'char *'/'const char *', por lo que en ese caso normalmente lanzo. – ideasman42

+8

@ppumkin Desafortunadamente, muchas funciones de cadenas de biblioteca estándar C toman argumentos como 'char *' incluso para cadenas que no se modificarán. Si tomas un parámetro como 'char const *' y lo pasas a una función estándar tomando un 'char *', lo presionarás. Si la función de la biblioteca no va a manipular la cadena, puede descartar el 'const'. – John

+0

El hecho de que no siempre sea posible no significa que no sea la opción preferida en muchas ocasiones, esta advertencia aparece en el código de producción común. – LovesTha

0

respuesta de BlackShift es muy útil, y lo usó como:

extern string execute(char* cmd) { 
      FILE* pipe = popen(cmd, "r"); 
      if (!pipe) return "ERROR"; 
      char buffer[256]; 
      std::string result = " "; 
      while(!feof(pipe)) { 
        if(fgets(buffer, 128, pipe) != NULL) 
          result += buffer; 
      } 
      pclose(pipe); 
      return result; 
    } 
    int main(){ 
      char cmd[]="grep -A1 'xml' out1.txt | grep read|awk -F'=' 'BEGIN{sum=0}{sum=sum+$NF}END{print sum}'"; 
      string result=execute(cmd); 
      int numOfBytes= atoi(result.c_str()); 
      cout<<"Number of bytes = "<<numOfBytes<<endl; 
      return 0; 
    } 
3

Haz encasillamiento de cadena constante a char puntero es decir

char *s = (char *) "constant string"; 
15

En lugar de:

void foo(char *s); 
foo("constant string"); 

Esto funciona:

void foo(const char s[]); 
foo("constant string"); 
+0

Esta es la forma correcta de hacerlo, ya que no debe pasar una cadena (constante) a una función que espera una cadena no constante de todos modos! – jfla

10

En C++, utilice el const_cast como, como a continuación

char* str = const_cast<char*>("Test string"); 
19

Reemplazar

char *str = "hello"; 

con

char *str = (char*)"hello"; 

o si está llamando a la función:

foo("hello"); 

reemplazar esto con

foo((char*) "hello"); 
0

Gracias, todos, por la ayuda. Escogiendo de aquí y allá viene esta solución. Esto compila limpio. No he probado el código todavía. Mañana ... tal vez ...

const char * timeServer[] = { "pool.ntp.org" }; // 0 - Worldwide 
#define WHICH_NTP   0 // Which NTP server name to use. 
... 
sendNTPpacket(const_cast<char*>(timeServer[WHICH_NTP])); // send an NTP packet to a server 
... 
void sendNTPpacket(char* address) { code } 

lo sé, sólo hay 1 elemento de la matriz del servidor de hora. Pero podría haber más. El resto se comentaron por ahora para ahorrar memoria.

0

En C++, reemplace:

char *str = "hello"; 

con:

std::string str ("hello"); 

Y si quieres compararlo:

str.compare("HALLO"); 
0

No entiendo cómo aplicar su solución :(- kalmanIsAGameChanger

Trabajando con Arduino Sketch, tenía una función que causaba mis advertencias.

función original: StrContains char (char * str, char * sfind)

Para detener las advertencias que añade el const frente al char * str y el carbón * sfind.

Modificado: StrContains char (const char * str, const char * sfind).

Todas las advertencias desaparecieron.

Cuestiones relacionadas