Veo C getcwd a través de:
hombre 3 cwd

Sospecho que C++ tiene una similar, que podría volver a mí a un std::string .

Si es así, cómo se llama y donde lo puedo encontrar documentación?

Gracias!

  • Por qué no usar simplemente std::string cwd = getcwd(); y dejar que el constructor de hacer su trabajo?
  • ¿Getcwd() pérdidas de memoria si no se libre de ella? Si es así, entonces usted debe libres después de la creación de la cadena, como contraposición a la libera cuando ya no la necesita, y que es más conveniente. Si no, entonces la inicialización de la cadena no pérdida de la memoria.
  • Puedo confirmar con valgrind – cadena de cwd = getcwd(NULL, 0); hace memoria de la fuga!
  • getcwd() asigna el búfer de forma dinámica mediante malloc(3) si buf es NULL
InformationsquelleAutor anon | 2010-02-04

8 Comentarios

  1. 26

    Ok, yo estoy respondiendo, aunque ya lo han aceptado una respuesta.

    Una mejor manera de envolver el getcwd llamada sería el uso de boost::sistema de archivos, de donde se obtiene un path objeto de la current_path() función. El Impulso del sistema de ficheros de la biblioteca le permite hacer un montón de cosas útiles que de otro modo tendrían que hacer un montón de análisis de cadenas para hacer, como la comprobación de si los archivos/directorios que existen, obtener la ruta de acceso principal, hacer rutas de acceso completa etcétera. Échale un vistazo, es portátil, así que un montón de la cadena código de análisis de lo contrario uno podría utilizar probable que no sea.

    Actualización (2016): sistema de Ficheros ha sido publicado como un especificación técnica en 2015, basado en el Impulso del sistema de Ficheros v3. Esto significa que puede estar disponible con el compilador ya (por ejemplo, Visual Studio 2015). A mí también me parece más probable es que va a formar parte de un futuro estándar de C++ (supongo que C++17, pero yo no soy consciente de la situación actual).

    Actualización (2017): La el sistema de ficheros de la biblioteca se ha fusionado con la ISO C++ en C++17, para

    std::filesystem::current_path();
    • Por supuesto, en algunas situaciones puede no ser la pena, incluyendo el boost::sistema de ficheros de la biblioteca sólo para obtener el directorio de trabajo actual. Aunque, si s/él está haciendo un montón de sistema de ficheros cosas, entonces se puede usar el boost para todos.
    • ¿Por qué cada respuesta boost::este boost::que?
    • No creo Impulso es siempre la respuesta. Pero en algunos casos lo es, y el uso de algo que ya existe y hace su vida más fácil es generalmente una buena cosa. Tenga en cuenta que algunas de las cosas que ahora están en el estándar de C++ vino de Boost y que estimulen el sistema de Ficheros está programado para su inclusión como una especificación técnica iirc.
    • La razón por la que dijo que es porque cada vez que alguien le pregunta cómo lograr una determinada tarea utilizando una API(s), la respuesta es siempre: el uso de esta biblioteca. Tiene sentido si estás trabajando en un proyecto grande, y usted tiene tiempo para tallar para familiarizarse con su nueva biblioteca, pero para una aplicación que sólo quiere obtener el directorio actual de trabajo que desea descargar una biblioteca sólo para eso? Bibliotecas de terceros sólo hacen que sea más difícil para depurar tu aplicación y como en este caso agregar nada, pero la hinchazón y el resultado es un grande de archivos fat.
    • Si entiendo correctamente, usted está diciendo que no es necesario agarrar una (gran) parte de terceros de la biblioteca sólo para obtener el directorio de trabajo actual. Esta parte estoy de acuerdo con alguna medida, sin embargo, el punto es que usted no es probable que simplemente interesados en el directorio que se va a utilizar, que para algo, es probable que la manipulación de rutas de acceso de archivo. En lugar de escribir algo de su propia, lo que probablemente va a tener errores y no portátiles se pueden utilizar en su lugar algo que ya existe y funciona. Boost puede ser demasiado grande para algunos casos de uso, pero no es necesario hacerlo todo.
    • Entonces quiere decir que «las bibliotecas de terceros sólo hacen que sea más difícil para depurar su aplicación» y «añadir nada pero hinchazón». Esta parte no puedo estar de acuerdo con. ¿Por qué perder el tiempo de depuración su propio código si hay algo más que ya no lo quieres hacer? Yo en cambio argumentan que el uso de (bien escrito) bibliotecas de terceros hace que sea más fácil de depurar su propio código, ya que escribir menos código.
    • Al incorporar el código de terceros, es más probable que se entorpecer o ralentizar el proceso de depuración de la aplicación. Algunas bibliotecas necesitan para inicializar y por lo tanto se debe ejecutar antes de su código. En ese proceso se puede hacer de la mierda que iba a hacer difícil de depurar el código, que viene después de la biblioteca.»¿Por qué perder el tiempo de depuración su propio código si hay algo más que ya no lo quieres hacer?» Si es demasiado grande para una tarea simple.
    • escrito) bibliotecas de terceros hace que sea más fácil de depurar su propio código, ya que escribir menos código» entonces, ¿qué te detiene la utilización de su propio (bien escrito) código con exactamente suficientes funciones como para su tarea?
    • Usted siempre tiene la opción de usar una biblioteca o para volver a escribir el mismo/mejor/parcial de funcionalidad del mismo. Es una ingeniería de la decisión que depende de donde usted piensa que su tiempo es lo mejor pasó, el riesgo de problemas, facilidad de uso, facilidad de mantenimiento, etc. IME, por lo general es mejor usar algo que ya existe, pero es imposible dar una regla absoluta, ya que la utilización de los casos son probablemente diferentes de la mía. También, IME, la auto-escrito de la biblioteca de reemplazos que escribe la gente tienden a ser buggy, no portátiles, la falta de funcionalidad, y una pesadilla para el uso. No parecen estar de acuerdo, ok.
    • Tal vez depende de que está escribiendo el código. Alguien que sabe lo que la codificación es más probable que tenga menos de que no hay errores.
    • Y mi reacción inicial no fue un desacuerdo, I código en ensamblador y cuando a veces estoy mirando cómo lograr algo en Windows normalmente me la conteste el uso de esta librería o biblioteca cuando sé que la lectura de la API de Windows, además de un poco de investigación me puede rodar fuera de mi en la Asamblea. Así que sí. Vamos a mantener las cosas como están y simplemente dar a la gente de nuestro vulnerables bibliotecas y ver a la gente hackeado porque el proveedor de software no sabía lo que su 3ª parte de código que realmente hace.
    • Gracias por probar mi punto… 🙂 Otro ejemplo de por qué rodar su propio suele ser una mala cosa es esta pregunta en sí misma. CAJERO automático hay 6 otras respuestas, ninguno de los cuales son portátiles ni tratar de unicode rutas de acceso en Windows. Otro punto: Impulsar el sistema de Ficheros es esencialmente lo que se convertirá en el sistema de archivos de la Especificación Técnica para C++. En mi humilde opinión, la elección entre el Impulso y enrollados a mano asamblea para cosas normales como esto es una obviedad para la mayoría de las aplicaciones. Una de las razones por las que hay un montón de código vulnerable en la naturaleza es que la gente escribe su propio lugar de utilizar algo existente.

  2. 23

    std::string‘s constructor puede tomar un char* como un parámetro. Sorprendentemente hay un la versión de windows demasiado.

    Edit: en realidad es un poco más complicado:

    std::string get_working_path()
    {
       char temp[MAXPATHLEN];
       return ( getcwd(temp, sizeof(temp)) ? std::string( temp ) : std::string("") );
    }

    La memoria no es problema — temp es una pila de búfer basado, y el std::string constructor hace una copia. Probablemente usted podría hacer en un solo paso, pero no creo que la norma garantiza que.

    Sobre la asignación de memoria, a través de POSIX:

    La getcwd() la función tendrá lugar una ruta de acceso absoluta del directorio de trabajo actual en el array apuntado por buf, y volver buf. El nombre de la ruta copiado a la matriz no debe contener componentes que son enlaces simbólicos. El argumento size es el tamaño en bytes de la matriz de caracteres apuntada por el buf argumento. Si buf es un puntero nulo, el comportamiento de getcwd() es indeterminado.

    • es el char * automatigally liberado? ¿o es que esta me da una pérdida de memoria?
    • Tanto esta respuesta y Liranuna comentario de uso getcwd como un no-argumento de la función, sin embargo, la documentación que yo veo, muestra dos parámetros. Estoy leyendo el mal docs?
    • no, el resultado char* es malloc ed y debe ser free d después de la creación de un std::string a partir de ella.
    • esa es una extensión no estándar, por lo que puedo contar. Linux, Mac y Windows, todos en práctica, que puede o no ser «lo suficientemente portátil.»
    • la especificación POSIX establece explícitamente que los datos se copian, no se asigna, por tanto, no es necesario liberar.
    • Lo siento, yo estaba mirando el no-parámetro de la versión antes de la edición cambió a tomar un búfer. Si utiliza la no-parámetro de la versión (o la no-estándar de la versión que mallocs si se le da un búfer NULL), entonces usted necesita para usar gratis.
    • -1 Potencial desbordamiento de búfer. El código de malo. ( asignará std::string basada en la basura en temp si getcwd falla, la basura no puede ser nul terminado; usted necesita para comprobar el valor de retorno de ::getcwd y tirar en el error )
    • las excepciones no son una solución que puede ser utilizado siempre que se abstengan de querer tirar todas partes. Sin embargo, la comprobación de errores fue no se incluye para el nivel de detalle como de costumbre en tales casos. Donde usted ve a un desbordamiento de búfer?
    • Si se produce un error, entonces el contenido de temp no están definidos. Como se crea una cadena con el único argumento del constructor de la espera de una cadena terminada en null, el constructor puede escanear fuera de la final antes de llegar a un nul. Por lo tanto, buffer (leer) de desbordamiento. Su código editado no tienen este problema, pero puede causar comportamiento extraño en lo que es utilizar el valor de retorno si lo hace no, a menos que el cliente de pruebas para una cadena vacía. Personalmente, yo no lo envuelva el posix función en todos, y dejar que el código de cliente de prueba documentados POSIX resultado en lugar de la prueba de vacío.
    • indefinido aquí en OSX 10.6

  3. 13

    Vamos a intentar y volver a escribir esta simple C llame como C++:

    std::string get_working_path()
    {
        char temp [ PATH_MAX ];
    
        if ( getcwd(temp, PATH_MAX) != 0) 
            return std::string ( temp );
    
        int error = errno;
    
        switch ( error ) {
            //EINVAL can't happen - size argument > 0
    
            //PATH_MAX includes the terminating nul, 
            //so ERANGE should not be returned
    
            case EACCES:
                throw std::runtime_error("Access denied");
    
            case ENOMEM:
                //I'm not sure whether this can happen or not 
                throw std::runtime_error("Insufficient storage");
    
            default: {
                std::ostringstream str;
                str << "Unrecognised error" << error;
                throw std::runtime_error(str.str());
            }
        }
    }

    La cosa es que, cuando un ajuste de una función de la biblioteca en otra función tiene que asumir que toda la funcionalidad debe ser expuesta, ya que una biblioteca no sabemos qué va a ser de una llamada. Así que usted tiene que manejar los casos de error, en vez de sólo la deglución ellos o con la esperanza de que no va a suceder.

    Lo general, es mejor dejar que el código de cliente que se llame a la función de la biblioteca, y lidiar con el error en ese punto – el código de cliente probablemente no le importa por qué se produjo el error, y por lo tanto sólo tiene que manejar la pass/fail caso, en lugar de todos los códigos de error.

    • Hay un error tipográfico. Debe ser != 0 en lugar de == 0 en la quinta línea.
  4. 6

    Tendrás que acaba de escribir un poco de contenedor.

    std::string getcwd_string( void ) {
       char buff[PATH_MAX];
       getcwd( buff, PATH_MAX );
       std::string cwd( buff );
       return cwd;
    }
    • tal vez intente std::string getcwd_string( void ) { string ret(PATH_MAX,0); getcwd( &ret[0], PATH_MAX ); ret.resize(ret.find_first_of('\0',0)); return ret; } – evitar VLA (que no es técnicamente parte de estándares de c++, al menos no todavía, aunque la mayoría de los compiladores de apoyo como una extensión del lenguaje)
    • Usted tiene que comprobar para nullptr (NULL) devuelve desde getcwd.
  5. 3

    Todas las funciones de C son también funciones de C++. Si usted necesita un std::string, crear uno de los char* que getcwd se presenta para usted.

  6. 3

    He utilizado getcwd() en C de la siguiente manera:

    char * cwd;
    cwd = (char*) malloc( FILENAME_MAX * sizeof(char) );
    getcwd(cwd,FILENAME_MAX);

    El archivo de encabezado necesarios es stdio.h.
    Cuando yo uso el compilador de C, funciona perfecto.

    Si puedo compilar exactamente el mismo código, usando el compilador de C++, se informa el siguiente mensaje de error:

    identifier "getcwd" is undefined

    Entonces yo incluido unistd.h y compilado con el compilador de C++.
    Esta vez, todo funciona.
    Cuando me vuelva a conectar el compilador de C, que todavía funciona!

    Siempre que incluya tanto stdio.h y unistd.h, el código anterior funciona para C Y C++ compiladores.

    • +1 para verificar en ambos compiladores, y volver a verificar que después de los cambios.
    • Uso PATH_MAX en lugar de FILENAME_MAX
  7. 1

    También he usado boost::sistema de archivos como se indica en otra respuesta anterior. Yo sólo quería añadir que desde el current_path() función no devuelve un std::string, usted necesita para convertir.

    Aquí es lo que yo hice:

    std::string cwd = boost::filesystem::current_path().generic_string();
  8. -2

    Se podría crear una nueva función, que yo preferiría través de la vinculación a una biblioteca como boost(a menos que ya lo son).

     std::string getcwd()
     {
         char* buff;//automatically cleaned when it exits scope
         return std::string(getcwd(buff,255));
     }
    • buff puntos a memoria no inicializada, y violación de segmento si tienes suerte
    • Oops! sí, asignar la memoria.

Dejar respuesta

Please enter your comment!
Please enter your name here